
Motion: Animation That Respects the User
Declarative animation in React, layout transitions that would take an afternoon by hand, and a reduced-motion story that is one hook rather than an audit finding.
Animation on the web fails in two directions. Either there is none, and state changes happen as jump cuts nobody can follow, or there is too much, and every scroll triggers something that makes the page feel slow and the user feel managed.
Motion is good at the first problem and honest about the second.
Declarative, so it survives refactors
import { motion } from 'motion/react'
<motion.div
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -8 }}
transition={{ duration: 0.22, ease: 'easeOut' }}
>
{children}
</motion.div>
You describe states, not frames. Nothing here breaks when the component moves in the tree, which is the failure mode of imperative timeline animation in a component framework.
The feature that earns the dependency
layout:
<motion.li layout transition={{ type: 'spring', stiffness: 400, damping: 32 }}>
When an item is filtered out of a list and everything below it moves up, that reflow animates smoothly. Doing this by hand means measuring positions before and after, computing deltas and applying inverted transforms. It is a known technique and it is still an afternoon of work per list. Here it is one prop.
Reduced motion is one hook, so there is no excuse
const reduced = useReducedMotion()
<motion.div
initial={reduced ? false : { opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: reduced ? 0 : 0.22 }}
/>
Vestibular disorders are real and the operating-system preference exists precisely so people can say so. A site that ignores it is not stylish, it is inaccessible. Because the check is a hook rather than a media-query rewrite, there is no scenario where doing it right is meaningfully more work.
Keep it on the compositor
Animate transform and opacity. Animating width, height, top or margin forces layout on every frame and will drop a mid-range phone below 60fps no matter which library you used. This is a browser fact, not a library one — but it is the single thing that separates animation that feels expensive from animation that feels cheap.
The editorial rule
Motion should explain what changed: where a panel came from, which item is new, that a value updated. If an animation is not answering a question the user just asked, it is decoration with a frame budget. I cut more animations in review than I add.
Resources
- Repo: motiondivision/motion
- Docs: motion.dev
- Video walkthroughs: YouTube: motion react framer animation tutorial
- Related: Radix Primitives: behaviour without the look
Need this built properly?
I build secure, fast, bilingual platforms for clients across Egypt, Saudi Arabia, the UAE and Kuwait.


