Animations with Framer Motion
By the end of this lesson you'll animate React UIs declaratively with Framer Motion (now the motion package): the motion.div component, initial / animate / exit , the transition prop, variants, AnimatePresence , gestures like whileHover , and layout animations.
Learn Animations with Framer Motion in our free React course — an interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free React course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn
1. The motion component
Framer Motion (published today as the motion package, historically framer-motion ) gives you animatable versions of every element: motion.div , motion.button , motion.li , and so on. They accept animation props. The two essentials: initial (where the animation starts) and animate (where it ends). When animate changes later, the element re-animates automatically.
Under the hood the library interpolates each property from its initial value to its animate value over time. Run this to see that frame-by-frame for opacity — declaring two endpoints and letting the library fill the gap:
Your turn. Describe a "slide in from the left and fade in" entrance as the objects you'd hand to a motion component. Fill in the three blanks, then run it and check the output.
2. The transition prop — timing & springs
The transition prop controls how the animation plays. For a tween you set duration and ease (e.g. "easeInOut" ). For natural, physics-based motion you use a spring ( type: "spring" ) tuned with stiffness and damping . You can also add a delay or stagger children. Springs feel best for interactive UI; tweens are predictable for precise timing.
3. Variants — named, reusable states
Variants are named animation states (like hidden and visible ) defined once in an object, then referenced by string. They keep your JSX clean, and — powerfully — a parent's variant can cascade to its children , letting you staggerChildren so a list animates in one item at a time.
4. AnimatePresence & gestures
There's a catch with exit animations: when you remove an element from the tree, React unmounts it immediately , leaving no time to animate out. AnimatePresence solves this — wrap conditionally-rendered elements in it, give them an exit prop, and the library keeps them mounted just long enough to play the exit animation. Add gestures like whileHover and whileTap for interactive feedback.
🔎 Layout animations
The layout prop is one of Framer Motion's most magical features. Add layout to a motion component and any time its size or position changes between renders, the library smoothly animates the difference — no manual measuring.
Great for reordering lists, expanding cards, or moving an item between columns. Combine with layoutId to animate an element as it moves from one place in the tree to another (shared-element transitions).
Tip: animating transform and opacity (which Framer Motion prefers) is GPU-accelerated and stays smooth.
5. Declarative vs manual animation
You can animate with CSS keyframes or by manually tweaking styles in a requestAnimationFrame loop — but you have to write every keyframe, track timing, and handle cleanup, and exit animations are genuinely painful. Framer Motion is declarative : you describe the states ( initial , animate , exit ) and the library computes the frames, orchestrates enter/exit, and interrupts gracefully when values change mid-flight. Less code, fewer bugs, smoother results.
Common Errors (and the fix)
- Exit animation never plays: the element isn't wrapped in AnimatePresence , so React removes it instantly. Wrap it and add an exit prop.
- Animating a plain element: you used <div> instead of <motion.div> . Only motion.* components read the animation props.
- Missing key in AnimatePresence: children that swap need a stable key so the library knows what entered and what left.
- Janky layout animation: you're animating width / top directly. Prefer the layout prop, which animates transform for smoothness.
- Ignoring reduced motion: some users set "reduce motion". Respect it with the useReducedMotion hook or a media query and tone animations down.
Pro Tips
- 💡 Animate transform and opacity (x, y, scale, rotate, opacity) — they're GPU-accelerated and stay buttery smooth.
- 💡 Reach for variants once an animation touches multiple elements or needs to stagger — they keep JSX readable.
- 💡 Springs feel alive for interactive UI; tweens are best when you need exact timing.
- 💡 Respect useReducedMotion() so users who get motion sick aren't forced into big animations.
📋 Quick Reference
Prop / API
What it does
motion.div
Animatable element that reads animation props
initial / animate
Start state / target state
exit
State to animate to when removed
transition
duration, ease, type: "spring", delay
variants
Named states; can stagger children
AnimatePresence
Enables exit animations on removal
whileHover / whileTap
Gesture-driven animation states
layout
Auto-animate size/position changes
Frequently Asked Questions
The library is now published as the motion package; framer-motion is the older name you'll still see widely. The component API ( motion.div , etc.) is the same.
React unmounts removed elements immediately. Wrap them in AnimatePresence and give them an exit prop so they animate out first.
Use a spring for natural, interactive motion (drags, hovers); use a tween with a fixed duration when you need exact, repeatable timing.
Yes — honor the user's reduced-motion preference with useReducedMotion() and avoid large or flashing motion that can trigger discomfort.
Mini-Challenge: a stagger schedule
No blanks this time — just a brief. Write staggerStarts(count, step) that returns each child's start time when a list staggers in. Run it and check your output against the expected line in the comments.
🎉 Lesson Complete
- ✅ motion.div and friends are animatable elements driven by props
- ✅ initial / animate / exit describe states; the library tweens between them
- ✅ transition sets duration, ease, or a physics-based spring
- ✅ Variants name reusable states and stagger children
- ✅ AnimatePresence enables exit animations; gestures and layout add polish
- ✅ Course wrap-up: you've finished the React course — go build something delightful!
Practice quiz
What is a motion component like motion.div?
- An animatable version of an element that accepts animation props
- A React hook
- A CSS class
- A plain div with no extra features
Answer: An animatable version of an element that accepts animation props. motion.div (and motion.button, motion.li, etc.) is an enhanced element that accepts props like initial, animate, and transition to animate it.
What does the initial prop define?
- The hover state
- The transition duration
- The state the element animates FROM when it first mounts
- The final state of the animation
Answer: The state the element animates FROM when it first mounts. initial sets the starting values; the element animates from initial toward the animate values on mount.
What does the animate prop define?
- The exit animation
- The target state the element animates TO
- The easing curve
- Whether animation is on or off
Answer: The target state the element animates TO. animate is the target the element animates toward; changes to it are also animated automatically.
Which prop controls how the animation plays (duration, easing, spring)?
- timing
- ease
- motion
- transition
Answer: transition. The transition prop configures duration, ease, type (tween or spring), delay, and other timing details.
What are variants used for?
- Defining named sets of animation states you can reference by name
- Importing the library
- Styling with CSS classes
- Lazy loading components
Answer: Defining named sets of animation states you can reference by name. Variants are named target objects (e.g. hidden/visible) you reference by name, and they can cascade to children.
Why do you need AnimatePresence?
- To pause all animations
- To animate elements as they are REMOVED from the tree (exit animations)
- To detect hover
- To animate elements when they ENTER
Answer: To animate elements as they are REMOVED from the tree (exit animations). React removes elements immediately, so AnimatePresence keeps them mounted long enough to run their exit animation.
Which prop animates an element while the user hovers over it?
- hoverAnimate
- animateHover
- onHover
- whileHover
Answer: whileHover. whileHover (and whileTap for press) animate to a target state for the duration of the gesture, then animate back.
What does adding the layout prop to a motion component do?
- Adds a CSS grid
- Locks the layout in place
- Automatically animates the element smoothly when its size or position changes
- Disables animation
Answer: Automatically animates the element smoothly when its size or position changes. The layout prop makes Framer Motion smoothly animate changes to an element's position and size between renders.
What kind of transition produces natural, physics-based motion?
- A linear tween
- A spring
- A step function
- An instant cut
Answer: A spring. A spring transition simulates physics (stiffness, damping) for natural-feeling motion, common for interactive UI.
What is the main advantage of Framer Motion over manual CSS/JS animation?
- It is declarative: you describe states and it handles the transitions, including enter/exit
- It is the only way to animate in React
- It removes the need for any styling
- It produces smaller bundles than no library
Answer: It is declarative: you describe states and it handles the transitions, including enter/exit. You declare the states (initial/animate/exit) and Framer Motion computes the in-between frames and orchestrates enter/exit, instead of manually writing keyframes and cleanup.
Continue this course
- Previous: Accessibility in React