react-transition-group vs framer-motion vs react-spring vs react-motion
Animation Libraries for React Applications
react-transition-groupframer-motionreact-springreact-motionSimilar Packages:

Animation Libraries for React Applications

framer-motion, react-spring, react-motion, and react-transition-group are tools for adding movement and transitions to React interfaces. framer-motion and react-spring are modern JavaScript-driven libraries that handle complex physics and gestures. react-transition-group is a lower-level utility for managing CSS-based enter/exit classes. react-motion is a legacy library that pioneered spring physics in React but is no longer the primary choice for new development.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
react-transition-group51,767,74610,246244 kB258-BSD-3-Clause
framer-motion35,115,37732,1144.73 MB1216 days agoMIT
react-spring988,29529,0977.23 kB895 days agoMIT
react-motion721,51621,929-1939 years agoMIT

Animation Libraries for React: Architecture and API Compared

Choosing the right animation library affects how you structure components, manage state, and handle performance. framer-motion, react-spring, react-motion, and react-transition-group all solve movement in React, but they use different engines and API styles. Let's compare how they handle common engineering tasks.

πŸ—οΈ Animation Engine: JavaScript vs CSS

The core difference lies in where the animation calculation happens. Some libraries calculate values in JavaScript on every frame, while others toggle CSS classes and let the browser handle the interpolation.

framer-motion calculates animations in JavaScript using a optimized engine.

  • It supports complex sequences and gestures out of the box.
  • You define values directly on the component.
// framer-motion: JS-driven animation
import { motion } from "framer-motion";

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

react-spring calculates animations in JavaScript using spring physics.

  • It interpolates values based on mass, tension, and friction.
  • You bind animated values to styles.
// react-spring: JS-driven spring animation
import { useSpring, animated } from "@react-spring/web";

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

react-motion calculates animations in JavaScript using spring physics (Legacy).

  • It uses a render-prop pattern to pass values.
  • No longer recommended for new development.
// react-motion: JS-driven spring animation (Legacy)
import { Motion, spring } from "react-motion";

function Box() {
  return (
    <Motion style={{ x: spring(100) }}>
      {({ x }) => <div style={{ transform: `translateX(${x}px)` }} />}
    </Motion>
  );
}

react-transition-group relies on CSS for the actual movement.

  • It adds class names at specific times (enter, active, exit).
  • You write the keyframes or transitions in your stylesheet.
// react-transition-group: CSS-driven animation
import { CSSTransition } from "react-transition-group";

function Box({ show }) {
  return (
    <CSSTransition in={show} timeout={300} classNames="fade">
      <div /> {/* CSS handles .fade-enter-active */}
    </CSSTransition>
  );
}

🧩 API Style: Hooks vs Components vs Render Props

How you define animation logic changes based on the library's age and design philosophy. Modern libraries favor hooks, while older ones use components or render props.

framer-motion uses special components with animation props.

  • You wrap standard HTML elements with motion.
  • State is managed internally unless controlled via props.
// framer-motion: Component-based API
<motion.button whileHover={{ scale: 1.1 }} onClick={handleClick} />

react-spring uses hooks combined with animated components.

  • You call useSpring to get animated values.
  • You must use animated components to apply those values.
// react-spring: Hook-based API
const props = useSpring({ opacity: isOpen ? 1 : 0 });
return <animated.div style={props} />;

react-motion uses a render-prop component pattern.

  • You wrap content in <Motion> and receive values in a function.
  • This creates deeper nesting in your JSX tree.
// react-motion: Render-prop API
<Motion style={{ opacity: spring(1) }}>
  {(styles) => <div style={{ opacity: styles.opacity }} />}
</Motion>

react-transition-group uses wrapper components to manage class lifecycle.

  • You wrap the element you want to animate.
  • You must manage the in prop manually to trigger states.
// react-transition-group: Lifecycle wrapper API
<CSSTransition in={isVisible} timeout={500} classNames="slide">
  <div>Content</div>
</CSSTransition>

πŸ“ Layout Animations: Automatic vs Manual

Animating layout shifts (like reordering a list) is notoriously difficult. Some libraries automate this using the FLIP technique, while others require manual measurement.

framer-motion supports automatic layout animations.

  • Add the layout prop to handle position changes automatically.
  • No need to calculate start and end positions manually.
// framer-motion: Automatic layout
<motion.li layoutId={`item-${id}`} onClick={() => setSelected(id)} />

react-spring requires manual measurement for layout changes.

  • You often need useMeasure to get element bounds.
  • You must map those bounds to spring values yourself.
// react-spring: Manual layout with useMeasure
const [ref, { width }] = useMeasure();
const props = useSpring({ width });
return <animated.div ref={ref} style={props} />;

react-motion requires manual measurement for layout changes.

  • You must track state changes and feed them to spring values.
  • Complex layout shifts often require significant boilerplate.
// react-motion: Manual layout
<Motion style={{ width: spring(newWidth) }}>
  {({ width }) => <div style={{ width }} />}
</Motion>

react-transition-group does not support JavaScript layout animations.

  • It only handles CSS class transitions.
  • Layout shifts must be handled via CSS transitions or other tools.
// react-transition-group: CSS only
/* No JS layout support β€” must use CSS transitions for width/height */

⚠️ Maintenance Status: Active vs Legacy

Using maintained software reduces security risks and ensures compatibility with future React versions. One of these packages is officially considered legacy.

framer-motion is actively maintained.

  • Regular updates support new React features.
  • Large community and extensive documentation.

react-spring is actively maintained.

  • Regular updates and active development.
  • Strong focus on physics and interpolation.

react-motion is legacy software.

  • The creator recommends migrating to react-spring.
  • Do not use for new projects due to lack of modern features.

react-transition-group is in maintenance mode.

  • Stable and rarely changes.
  • Maintained by the React community for basic use cases.

🀝 Similarities: Shared Ground

Despite their differences, these libraries share common goals and patterns.

1. βš›οΈ React Integration

  • All four libraries are built specifically for React.
  • They rely on component lifecycles or hooks to trigger animations.
// All libraries rely on React state to trigger changes
const [open, setOpen] = useState(false);
// Animation triggers when 'open' changes

2. 🎞️ Enter/Exit Transitions

  • All support mounting and unmounting elements with animation.
  • Each handles the timing of removal differently (JS vs CSS).
// framer-motion
<motion.div exit={{ opacity: 0 }} />

// react-transition-group
<CSSTransition in={show} classNames="fade" />

3. πŸ› οΈ TypeScript Support

  • Modern versions of all packages include type definitions.
  • Enables autocomplete and type safety in editors.
// All support TypeScript props
interface Props { isOpen: boolean; }

πŸ“Š Summary: Key Differences

Featureframer-motionreact-springreact-motionreact-transition-group
EngineJavaScriptJavaScript (Springs)JavaScript (Springs)CSS Classes
API StyleDeclarative PropsHooks + AnimatedRender PropsWrapper Components
LayoutAutomatic (layout)Manual (useMeasure)ManualNone
StatusActiveActiveLegacyMaintenance
Best ForInteractionsPhysicsLegacy SupportSimple CSS

πŸ’‘ The Big Picture

framer-motion is like a high-level animation studio 🎬 β€” it handles the heavy lifting for you. Ideal for dashboards, interactive prototypes, and apps needing gesture support.

react-spring is like a physics engine βš™οΈ β€” it gives you control over the forces driving the movement. Perfect for data visualizations and custom physical interactions.

react-transition-group is like a CSS helper 🎨 β€” it bridges React state and stylesheets. Best for simple fades or slides where performance is critical.

react-motion is like a classic car πŸš— β€” it pioneered the space but is outdated. Only use if maintaining existing legacy code.

Final Thought: For most modern applications, framer-motion offers the best balance of power and ease of use. If you need pure physics control, react-spring is the strong alternative. Avoid react-motion in new work.

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

  • react-transition-group:

    Choose react-transition-group if you want to keep animation logic in CSS files and only need simple enter/exit transitions. It is suitable for lightweight projects where JavaScript-driven animation is unnecessary.

  • framer-motion:

    Choose framer-motion if you need a declarative API with built-in support for layout animations, gestures, and complex sequences. It is ideal for production apps requiring high-fidelity interactions without manual physics tuning.

  • react-spring:

    Choose react-spring if you prefer a physics-based approach where animations are driven by spring constants rather than durations. It fits well when you need fine-grained control over interpolated values and functional composition.

  • react-motion:

    Do not choose react-motion for new projects as it is legacy software superseded by react-spring. Only use it if you are maintaining an older codebase that already depends on its specific render-prop API.

README for react-transition-group

react-transition-group npm

ATTENTION! To address many issues that have come up over the years, the API in v2 and above is not backwards compatible with the original React addon (v1-stable).

For a drop-in replacement for react-addons-transition-group and react-addons-css-transition-group, use the v1 release. Documentation and code for that release are available on the v1-stable branch.

We are no longer updating the v1 codebase, please upgrade to the latest version when possible

A set of components for managing component states (including mounting and unmounting) over time, specifically designed with animation in mind.

Documentation

TypeScript

TypeScript definitions are published via DefinitelyTyped and can be installed via the following command:

npm install @types/react-transition-group

Examples

Clone the repo first:

git@github.com:reactjs/react-transition-group.git

Then run npm install (or yarn), and finally npm run storybook to start a storybook instance that you can navigate to in your browser to see the examples.