Framer Motion logo

Framer Motion

The de facto standard for production-grade React animations, featuring declarative syntax and automatic layout transitions.

npm install framer-motion
30.4K11.1M/weekv12.23.242.23 MBMIT312 issues
Last updated: 2025-10-10
Star history chart for framer/motion

TL;DR

An open-source motion library for React that treats animations as declarative side-effects of state changes rather than imperative commands.

Famous for its 'Magic Motion' layout animations and intuitive API that abstracts away complex FLIP calculations, making it the default choice for modern React apps.

Why Framer Motion?

Framer Motion has largely won the "animation wars" in the React ecosystem by prioritizing Developer Experience (DX) above all else. While other libraries require understanding physics or complex imperative logic, Framer Motion allows you to describe what you want to happen, not how to calculate the frames.

  • Declarative Layout Animations: The layout prop is arguably its strongest feature. It automatically handles FLIP (First, Last, Invert, Play) calculations, allowing elements to smoothly animate to new positions when the DOM layout changes (e.g., reordering a list).
  • Variant Orchestration: Managing complex sequences where parent and child animations need to be synchronized (like staggering a list of items) is trivial using variants.
  • Production-Ready Gestures: It includes a complete gesture system supporting drag, pan, hover, and tap with physics-based constraints, eliminating the need for separate gesture libraries.
  • Shared Layout Transitions: The <LayoutGroup> and layoutId props enable distinct components to morph into one another, creating seamless "hero" transitions between routes or UI states.
  • Accessibility First: It respects the user's prefers-reduced-motion setting automatically, ensuring your app remains accessible without extra configuration.

Code Snippet

This example demonstrates Variants, a powerful pattern to orchestrate animations across a component tree. Notice how the parent controls the timing of its children without passing props manually.

import { motion } from "framer-motion";

// 1. Define animation states (Variants)
const listVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      when: "beforeChildren", // Wait for this to finish before starting children
      staggerChildren: 0.1    // Delay each child by 0.1s
    }
  }
};

const itemVariants = {
  hidden: { x: -20, opacity: 0 },
  visible: { x: 0, opacity: 1 }
};

export const Menu = ({ items }) => (
  // 2. Bind variants to the motion component
  <motion.ul
    initial="hidden"
    animate="visible"
    variants={listVariants}
    style={{ listStyle: "none" }}
  >
    {items.map((item) => (
      // 3. Children automatically inherit "hidden" and "visible" states
      <motion.li key={item.id} variants={itemVariants}>
        {item.label}
      </motion.li>
    ))}
  </motion.ul>
);

The beauty of this pattern is that motion.li doesn't need to know when to animate. The parent motion.ul propagates the animate="visible" state down the tree, and the staggerChildren property handles the delay automatically.

Pros and Cons

No library is perfect; understanding the trade-offs is key to selecting the right tool.

Pros

  • Unmatched DX: The API is incredibly intuitive for React developers. It feels like standard CSS-in-JS but with superpowers.
  • Layout Magic: Animating between DOM states (width/height/position changes) is often as simple as adding layout.
  • Documentation: The documentation is world-class, featuring interactive sandboxes for almost every feature.
  • Ecosystem Integration: Works flawlessly with popular CSS-in-JS libraries and Tailwind (via standard className or style props).

Cons

  • Bundle Size: It is heavier than alternatives like react-spring or vanilla CSS. While LazyMotion exists to reduce initial load, the full library is substantial (~30kb gzipped).
  • Performance Overhead: For simple interactions (like hover states), it adds JavaScript overhead where CSS transitions would be virtually free.
  • Runtime Cost: Heavy usage of layout animations on complex trees can cause frame drops on lower-end devices if not optimized (e.g., using will-change).

Comparison with Other Animation Libraries

The table below outlines the positioning differences between Framer Motion and other popular animation libraries to help you make an informed decision:

LibraryDesign PhilosophyBest ForPain Points
Framer MotionDeclarative & CSS-like
Focuses on defining states (start/end) and letting the library handle the transition logic.
Complex UI & Layouts
Applications needing shared layout transitions, gesture handling, and orchestrated sequences.
Bundle Size
Can be overkill for simple micro-interactions; heavier initial load.
React SpringPhysics-based
Simulates real-world physics (mass, tension, friction) rather than time-based durations.
Fluid Interactions
UIs that need to feel "natural" and interruptible (e.g., drag-and-throw interfaces).
Learning Curve
The API is more imperative and mathematical; harder to orchestrate complex sequences.
Anime.jsImperative & Agnostic
A powerful JavaScript animation engine that isn't tied to React's render cycle.
Creative WebGL/Canvas
Complex timelines or animations outside the React component tree (e.g., HTML5 Canvas).
React Integration
Requires manual useEffect refs management; fights against React's declarative nature.

Verdict: When to Adopt

Framer Motion is the default recommendation for 95% of React applications. If you are building a product dashboard, a marketing site, or a mobile-web app, its layout capabilities and ease of use outweigh the bundle size cost.

Choose React Spring only if you are building a highly interactive, physics-driven experience (like a card-swiping game) where "natural" momentum is critical. Choose Anime.js only if you are orchestrating complex timelines that are largely independent of React state.