framer-motion vs react-spring vs react-transition-group
Selecting React Animation Libraries for Production Apps
framer-motionreact-springreact-transition-groupSimilar Packages:

Selecting React Animation Libraries for Production Apps

framer-motion, react-spring, and react-transition-group are the leading solutions for adding motion to React applications, but they solve different problems. framer-motion offers a declarative API focused on developer experience and complex layout animations. react-spring provides physics-based animations for natural movement and granular control over values. react-transition-group is a low-level utility that manages CSS class switching during component enter/exit phases, often serving as the foundation for other libraries.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
framer-motion031,8644.73 MB1262 months agoMIT
react-spring029,0848.36 kB1378 months agoMIT
react-transition-group010,248244 kB258-BSD-3-Clause

React Animation Libraries: Framer Motion vs React Spring vs React Transition Group

Adding motion to a React app improves user experience, but picking the right tool affects maintenance and performance. framer-motion, react-spring, and react-transition-group are the top choices, yet they work in fundamentally different ways. This guide compares their APIs, performance characteristics, and best use cases to help you decide.

🏗️ Core Philosophy: Declarative vs Physics vs CSS

The biggest difference lies in how you define movement. framer-motion uses a declarative approach where you state the end result. react-spring uses physics springs to calculate values over time. react-transition-group relies on CSS classes that you define separately.

framer-motion lets you animate props directly on components.

import { motion } from "framer-motion";

function Box() {
  return <motion.div animate={{ x: 100, opacity: 1 }} />;
}

react-spring requires you to create a spring hook and pass values to an animated component.

import { useSpring, animated } from "@react-spring/web";

function Box() {
  const props = useSpring({ x: 100, opacity: 1 });
  return <animated.div style={props} />;
}

react-transition-group toggles CSS classes based on component state.

import { CSSTransition } from "react-transition-group";
import "./styles.css";

function Box({ show }) {
  return (
    <CSSTransition in={show} timeout={300} classNames="fade">
      <div className="box" />
    </CSSTransition>
  );
}

🚪 Handling Mount and Unmount Animations

Animating elements as they enter or leave the DOM is a common requirement. Each library handles this differently, especially regarding elements that are removed from the React tree.

framer-motion uses AnimatePresence to keep components alive until their exit animation finishes.

import { motion, AnimatePresence } from "framer-motion";

function List({ items }) {
  return (
    <AnimatePresence>
      {items.map((item) => (
        <motion.div
          key={item.id}
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
        />
      ))}
    </AnimatePresence>
  );
}

react-spring typically uses useTransition to manage mounting and unmounting logic internally.

import { useTransition, animated } from "@react-spring/web";

function List({ items }) {
  const transitions = useTransition(items, {
    key: (item) => item.id,
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
  });
  return transitions((style, item) => <animated.div style={style} />);
}

react-transition-group relies on the in prop to trigger classes before the element is removed.

import { TransitionGroup, CSSTransition } from "react-transition-group";

function List({ items }) {
  return (
    <TransitionGroup>
      {items.map((item) => (
        <CSSTransition key={item.id} timeout={300} classNames="fade">
          <div />
        </CSSTransition>
      ))}
    </TransitionGroup>
  );
}

🎛️ Physics vs Keyframes Control

Sometimes you need natural movement that mimics real-world physics. Other times, you need precise keyframe control.

framer-motion supports both keyframes and spring transitions via the transition prop.

<motion.div
  animate={{ x: 100 }}
  transition={{ type: "spring", stiffness: 100 }}
/>

react-spring is built entirely on physics. You configure mass, tension, and friction.

const props = useSpring({
  from: { x: 0 },
  to: { x: 100 },
  config: { mass: 1, tension: 170, friction: 26 },
});

react-transition-group does not support physics. You define timing functions in CSS.

/* styles.css */
.fade-enter-active {
  transition: opacity 300ms ease-in-out;
}

⚡ Performance and Under the Hood

Performance matters when animating many elements or running on low-power devices.

framer-motion optimizes renders by batching updates and using layout projections. It handles complex layout shifts efficiently without manual calculation.

react-spring drives animations using requestAnimationFrame and updates styles directly. This avoids React re-renders for every frame, which is great for high-frequency updates.

react-transition-group is the lightest weight. It only toggles classes, leaving the actual animation work to the browser's CSS engine. This is efficient but limits dynamic control.

📊 Summary Table

Featureframer-motionreact-springreact-transition-group
API StyleDeclarative ComponentsFunctional HooksCSS Class Toggles
PhysicsBuilt-in OptionCore FoundationNot Supported
Layout AnimationAutomaticManual CalculationNot Supported
Exit AnimationsAnimatePresenceuseTransitionin prop + CSS
Bundle WeightModerateModerateVery Low
Learning CurveLowMediumLow

💡 Final Recommendation

Pick the tool that matches your project's complexity and team skills.

framer-motion is the best all-rounder for modern React apps. It handles layout shifts, gestures, and standard animations with minimal code. Use it for dashboards, marketing sites, and interactive UIs where development speed matters.

react-spring shines when you need natural motion or complex chains. If you are building a game-like interface or need to interpolate values manually for performance, this is the right choice.

react-transition-group is still useful for simple cases. If you only need to fade a modal in and out and want to keep animation logic in CSS, this library adds almost no overhead.

Final Thought: All three libraries are stable and maintained. Your decision should depend on whether you prefer declarative syntax, physics control, or CSS-based simplicity.

How to Choose: framer-motion vs react-spring vs react-transition-group

  • framer-motion:

    Choose framer-motion if you need a batteries-included solution with powerful layout animations, gesture support, and a declarative API. It is ideal for product teams that want to ship polished interactions quickly without managing physics configurations manually.

  • react-spring:

    Choose react-spring if your application requires physics-based movements, complex chains of animations, or direct access to animated values for performance-critical interfaces. It suits developers who prefer functional hooks and need fine-grained control over interpolation.

  • react-transition-group:

    Choose react-transition-group if you only need simple CSS-based enter/exit transitions and want to avoid JavaScript-driven animation logic. It is best for lightweight projects, legacy codebases, or when you want to keep animation styles strictly within your CSS files.

README for framer-motion

Motion logo
Motion for React

An open source animation library
for React

npm version npm downloads per month jsDelivr hits (npm) NPM License

npm install motion

Table of Contents

  1. Why Motion?
  2. 🍦 Platforms
  3. 🎓 Examples
  4. ⚡️ Motion+
  5. 👩🏻‍⚖️ License
  6. 💎 Contribute
  7. ✨ Sponsors

Why Motion?

  • Simple API: First-class React, JavaScript, and Vue packages.
  • Hybrid engine: Power of JavaScript combined with native browser APIs for 120fps, GPU-accelerated animations.
  • Production-ready: TypeScript, extensive test suite, tree-shakable, tiny footprint. Batteries included: Gestures, springs, layout transitions, scroll-linked effects, timelines.

🍦 Platforms

Motion is available for React, JavaScript and Vue.

React

import { motion } from "motion/react"

function Component() {
    return <motion.div animate={{ x: 100 }} />
}

Get started with Motion for React.

Note: Framer Motion is now Motion. Import from motion/react instead of framer-motion.

JS

import { animate } from "motion"

animate("#box", { x: 100 })

Get started with JavaScript.

Vue

<script>
    import { motion } from "motion-v"
</script>

<template> <motion.div :animate={{ x: 100 }} /> </template>

Get started with Motion for Vue.

🎓 Examples & tutorials

Browse 330+ official examples, with copy-paste code that'll level-up your animations whether you're a beginner or an expert.

Over 100 examples come with a full step-by-step tutorial.

⚡️ Motion+

A one-time payment, lifetime-updates membership:

  • 330+ examples
  • 100+ tutorials
  • Premium APIs like Cursor and Ticker
  • Transition editor for Cursor and VS Code
  • AI skills
  • Private Discord
  • Early access content

Get Motion+

👩🏻‍⚖️ License

  • Motion is MIT licensed.

💎 Contribute

✨ Sponsors

Motion is sustainable thanks to the kind support of its sponsors.

Become a sponsor

Partners

Motion powers the animations for all websites built with Framer, the web builder for creative pros. The Motion website itself is built on Framer, for its delightful canvas-based editing and powerful CMS features.

Framer

Motion drives the animations on the Cursor homepage, and is working with Cursor to bring powerful AI workflows to the Motion examples and docs.

Cursor

Platinum

Linear Figma Sanity Sanity Clerk Greptile

Gold

Mintlify

Silver

Liveblocks Frontend.fyi Firecrawl Puzzmo Bolt.new

Personal