How to Animate React Components with Motion

Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.

6 min read

Motion, previously called Framer Motion, is a React animation library where animations live as props on components. Instead of imperatively starting tweens, you describe the resting state and Motion animates to it, which fits React's declarative model. One library covers enter, exit, hover, tap, drag, and scroll driven effects.

Install Motion

The package is named motion, and all React features come from the motion/react entry point.

bashbash
npm install motion

There is no plugin or config file. Import the motion component and prefix any element name with motion to unlock the animation props.

App.jsxApp.jsx
import { motion } from "motion/react";
 
export function FadeIn() {
  return <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} />;
}

The motion.div works exactly like a div but accepts animation props. Here it fades from invisible to visible when the component mounts.

Animate enter, hover, and tap

The same component can describe several states at once. initial sets the starting value, animate the resting value, and whileHover plus whileTap the gesture feedback.

App.jsxApp.jsx
<motion.button
  initial={{ scale: 0 }}
  animate={{ scale: 1 }}
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.95 }}
>
  Save changes
</motion.button>

The button grows in on mount, swells slightly on hover, and shrinks while pressed. Physical properties like scale use spring physics by default, while visual properties like opacity use tween easing, so each state feels natural without extra tuning.

Animate exits with AnimatePresence

By default React removes an element from the DOM instantly, so there is nothing left to animate. AnimatePresence keeps a component mounted while its exit animation plays.

App.jsxApp.jsx
import { AnimatePresence, motion } from "motion/react";
 
<AnimatePresence>
  {visible && (
    <motion.div
      key="notice"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    />
  )}
</AnimatePresence>

When visible flips to false, the notice fades out before React unmounts it. The key helps AnimatePresence track the element across renders, which is the same technique a fading accessible modal relies on when it closes.

Springs versus tweens

Motion chooses the animation type by the value. Physical properties such as x, y, and scale use spring physics, which gives a slight overshoot that feels natural for movement. Visual properties such as opacity and color use tween easing, which moves at a steady rate.

You can override either with the transition prop, setting a duration, an easing curve, or spring stiffness. Most components never need it, because the defaults already match how each value should feel, and the control is there for the rare moments a design calls for a specific feel.

Respect reduced motion

Some users disable motion at the operating system level, and animations should follow that choice. The useReducedMotion hook reports the preference.

App.jsxApp.jsx
import { useReducedMotion } from "motion/react";
 
function SaveButton() {
  const prefersReducedMotion = useReducedMotion();
 
  return (
    <motion.button
      whileHover={prefersReducedMotion ? undefined : { scale: 1.05 }}
    >
      Save
    </motion.button>
  );
}

When the preference is on, the hover effect is skipped and the button stays static. A broader version of this rule, covering CSS and other libraries, is in how to respect reduced motion.

Rune AI

Rune AI

Key Insights

  • Install motion and import from motion/react.
  • Use motion.div and motion.button for animated elements.
  • Set initial and animate for enter animations.
  • Use whileHover and whileTap for gesture feedback.
  • Wrap exits in AnimatePresence and respect useReducedMotion.
RunePowered by Rune AI

Frequently Asked Questions

Is Motion the same as Framer Motion?

Yes. The library was renamed from Framer Motion to Motion, and the current npm package is motion. Import everything from motion/react.

When is CSS animation enough?

A simple hover color change is fine in CSS. Motion earns its keep for enter and exit animations, spring physics, gestures, and coordinated sequences that CSS cannot express cleanly.

How do I respect reduced motion with Motion?

Call the useReducedMotion hook to detect the user preference, and skip transform or motion effects when it returns true. You can also wrap the tree in MotionConfig with reducedMotion set to user.

Conclusion

Motion animates React components through the motion component and props like animate, whileHover, and exit. Install the motion package, import from motion/react, and add reduced motion support so animations never override a user preference.