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.
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.
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.
// 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.
// 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).
// 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.
// 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>
);
}
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.
motion.// framer-motion: Component-based API
<motion.button whileHover={{ scale: 1.1 }} onClick={handleClick} />
react-spring uses hooks combined with animated components.
useSpring to get animated values.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.
<Motion> and receive values in a function.// 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.
in prop manually to trigger states.// react-transition-group: Lifecycle wrapper API
<CSSTransition in={isVisible} timeout={500} classNames="slide">
<div>Content</div>
</CSSTransition>
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.
layout prop to handle position changes automatically.// framer-motion: Automatic layout
<motion.li layoutId={`item-${id}`} onClick={() => setSelected(id)} />
react-spring requires manual measurement for layout changes.
useMeasure to get element bounds.// 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.
// react-motion: Manual layout
<Motion style={{ width: spring(newWidth) }}>
{({ width }) => <div style={{ width }} />}
</Motion>
react-transition-group does not support JavaScript layout animations.
// react-transition-group: CSS only
/* No JS layout support — must use CSS transitions for width/height */
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.
react-spring is actively maintained.
react-motion is legacy software.
react-spring.react-transition-group is in maintenance mode.
Despite their differences, these libraries share common goals and patterns.
// All libraries rely on React state to trigger changes
const [open, setOpen] = useState(false);
// Animation triggers when 'open' changes
// framer-motion
<motion.div exit={{ opacity: 0 }} />
// react-transition-group
<CSSTransition in={show} classNames="fade" />
// All support TypeScript props
interface Props { isOpen: boolean; }
| Feature | framer-motion | react-spring | react-motion | react-transition-group |
|---|---|---|---|---|
| Engine | JavaScript | JavaScript (Springs) | JavaScript (Springs) | CSS Classes |
| API Style | Declarative Props | Hooks + Animated | Render Props | Wrapper Components |
| Layout | Automatic (layout) | Manual (useMeasure) | Manual | None |
| Status | Active | Active | Legacy | Maintenance |
| Best For | Interactions | Physics | Legacy Support | Simple CSS |
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.
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.
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.
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.
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.
npm install motion
Motion is available for React, JavaScript and Vue.
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.
import { animate } from "motion"
animate("#box", { x: 100 })
Get started with JavaScript.
<script>
import { motion } from "motion-v"
</script>
<template> <motion.div :animate={{ x: 100 }} /> </template>
Get started with Motion for Vue.
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.
A one-time payment, lifetime-updates membership:
Motion is sustainable thanks to the kind support of its sponsors.
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.
Motion drives the animations on the Cursor homepage, and is working with Cursor to bring powerful AI workflows to the Motion examples and docs.