# CSS Animations vs Framer Motion for Performance: Which Is Faster?

> Compare CSS animations vs Framer Motion for performance. Discover which animation method offers faster frame rates and understand their impact on CPU usage for your web projects.

- Repository: [Emil Kowalski/skills](https://github.com/emilkowalski/skills)
- Tags: performance
- Published: 2026-08-04

---

**CSS animations generally deliver higher frame rates for simple transitions by executing directly on the browser's compositor thread without JavaScript overhead, while Framer Motion adds a runtime layer that enables complex physics-based interactions at the cost of increased CPU usage.**

Choosing between CSS animations and Framer Motion impacts your React application's rendering performance and bundle size. According to the animation optimization guidelines in the `emilkowalski/skills` repository, understanding the execution path from declaration to GPU compositing is essential when evaluating **CSS animations vs Framer Motion for performance**. This analysis examines the architectural differences, runtime costs, and specific use cases where each approach excels.

## Execution Path: Stylesheets vs JavaScript Loops

### CSS Animation Pipeline

In [`README.md`](https://github.com/emilkowalski/skills/blob/main/README.md), the repository notes that CSS animations are declared in stylesheets or inline styles, where the browser parses the CSS and creates a *CSS Animation* object directly. The browser hands this object straight to the compositor without requiring JavaScript after the initial style application. This direct path eliminates main-thread work during the animation lifecycle.

### Framer Motion's Runtime Layer

As documented in [`skills/review-animations/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/SKILL.md), Framer Motion translates React prop changes into `requestAnimationFrame` callbacks. Each frame updates the element's style through JavaScript before reaching the compositor. This additional abstraction layer, while providing rich orchestration capabilities, introduces runtime overhead that CSS animations avoid.

## CPU and GPU Utilization

Both technologies ultimately rely on the browser's compositor, but their CPU impact differs significantly.

When animating **transform** and **opacity** properties, CSS animations offload work entirely to the GPU. The animation runs on the compositor thread using minimal CPU resources, as the browser handles interpolation natively.

Framer Motion also encourages GPU-friendly properties, but because it maintains a JavaScript loop via `requestAnimationFrame`, the CPU remains active throughout the animation. Spring-based physics calculations particularly tax the main thread, potentially causing frame drops on lower-end devices if not carefully optimized.

## Layout Thrashing and Reflow Risks

Pure CSS animations avoid layout recalculations when confined to compositor-only properties. Changing `width`, `height`, or positional properties like `top` forces synchronous layout (reflow), which is costly regardless of the technology used.

However, Framer Motion's API allows animating any numeric value, including layout-affecting properties. The [`skills/improve-animations/PLAN-TEMPLATE.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/PLAN-TEMPLATE.md) file warns that developers must manually avoid reflow when animating these properties. While the library provides utilities like `layout` and `layoutId` to mitigate layout thrashing through FLIP techniques, the risk of forcing re-flow remains higher than with declarative CSS.

## Bundle Size and Runtime Cost

**CSS Animations** carry zero runtime JavaScript cost; only the CSS payload downloads and parses. This makes them ideal for performance-critical applications requiring minimal bundle overhead.

**Framer Motion** adds approximately 30 KB gzipped to your bundle, plus the React dependency if not already present. This cost is justified for complex interaction patterns but represents unnecessary overhead for simple fade-ins or slides.

## Practical Implementation Examples

The following examples demonstrate equivalent implementations and highlight when to choose each approach.

### Simple Fade-In with CSS

```css
.fade-in {
  animation: fadeIn 300ms ease-out forwards;
}

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

```

The browser parses this rule once, then the compositor handles the opacity transition without JavaScript involvement.

### Equivalent Framer Motion Component

```tsx
import { motion } from "framer-motion";

export function FadeIn() {
  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      transition={{ duration: 0.3, ease: "easeOut" }}
    >
      Hello, Framer Motion!
    </motion.div>
  );
}

```

Here, Framer Motion creates a `requestAnimationFrame` loop that updates `opacity` each frame. The visual result matches CSS, but with added JavaScript overhead.

### Complex Interaction Requiring Framer Motion

```tsx
import { motion } from "framer-motion";

export function DraggableCard() {
  return (
    <motion.div
      drag
      dragConstraints={{ left: 0, right: 300, top: 0, bottom: 300 }}
      whileTap={{ scale: 0.95 }}
      whileHover={{ scale: 1.02 }}
    >
      Drag me!
    </motion.div>
  );
}

```

Drag constraints, spring physics, and gesture handling are impractical with pure CSS, making Framer Motion the optimal choice despite its runtime cost.

## Decision Framework: When to Use Each

Use **CSS animations** for isolated, non-interactive transforms like fade-ins, slides, or rotations. Reserve them for [`skills/find-animation-opportunities/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/find-animation-opportunities/SKILL.md) scenarios where motion adds value without requiring runtime state coordination.

Use **Framer Motion** when implementing interactive, physics-driven, or sequenced animations that are difficult to express in CSS. As noted in [`skills/pick-ui-library/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/pick-ui-library/SKILL.md), the library's declarative API reduces development complexity for complex UI flows, but requires profiling with Chrome DevTools to ensure the JavaScript thread isn't a bottleneck.

## Summary

- **CSS animations** execute directly on the compositor thread without JavaScript overhead, making them faster for simple transitions.
- **Framer Motion** adds a `requestAnimationFrame` layer that enables complex physics and gestures but increases CPU usage.
- Animating `transform` and `opacity` properties provides GPU acceleration for both approaches.
- CSS carries zero runtime cost, while Framer Motion adds ~30 KB gzipped.
- Use CSS for static motion; use Framer Motion for interactive, coordinated sequences requiring springs or drag physics.

## Frequently Asked Questions

### Are CSS animations always faster than Framer Motion?

For simple transitions like fades and slides, yes. CSS animations bypass the JavaScript main thread entirely after initialization, while Framer Motion maintains an active `requestAnimationFrame` loop. However, for complex orchestrated animations, Framer Motion's optimized internals may outperform poorly written CSS or JavaScript-heavy alternatives.

### Can Framer Motion animations run on the GPU?

Yes, when animating `transform` and `opacity` properties, Framer Motion leverages the same GPU compositing as CSS. The performance difference stems from the JavaScript execution required to calculate each frame's values, particularly for spring physics, not from the final rendering path.

### How do I avoid layout thrashing with Framer Motion?

Avoid animating layout-affecting properties like `width`, `height`, or `top`. Instead, use the `layout` or `layoutId` props mentioned in [`skills/improve-animations/PLAN-TEMPLATE.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/PLAN-TEMPLATE.md), which implement FLIP (First, Last, Invert, Play) techniques to animate layout changes without forcing reflow. Stick to `transform` and `opacity` for optimal performance.

### Should I use Framer Motion if my app only has simple hover effects?

No. For simple hover states and static transitions, CSS transitions or keyframes provide better performance with zero JavaScript overhead. Reserve Framer Motion for interactions requiring physics, drag gestures, or complex exit/enter orchestration that CSS cannot express efficiently.