Creating Stunning Animations with Framer Motion
Good animation is communication: it tells the user what changed, where things came from, and what to look at. Framer Motion makes physics-based motion declarative — you describe the end state, it handles the spring.
From CSS Transitions to Springs
The core primitive is the motion component. Give it initial, animate, and transition props and it takes care of the rest:
import { motion } from 'framer-motion'; <motion.div initial={{ opacity: 0, y: 24 }} animate={{ opacity: 1, y: 0 }} transition={{ type: 'spring', stiffness: 260, damping: 20 }}> Hello, motion!</motion.div>Gestures and Scroll
Hover, tap, drag, and in-view triggers are one-liners. This card lifts on hover, squashes on tap, and only animates in when it scrolls into the viewport:
<motion.article whileHover={{ y: -4, scale: 1.02 }} whileTap={{ scale: 0.97 }} initial={{ opacity: 0 }} whileInView={{ opacity: 1 }} viewport={{ once: true, margin: "-80px" }}/>Orchestrating Sequences
Individual animations are easy; the craft is in choreography. Variants let a parent orchestrate its children — one prop change at the top ripples down with automatic stagger, which is how you get those satisfying cascading list entrances:
const list = { hidden: { opacity: 0 }, show: { opacity: 1, transition: { staggerChildren: 0.08 }, },}; <motion.ul variants={list} initial="hidden" animate="show"> {items.map((i) => <motion.li key={i} variants={item} />)}</motion.ul>Two rules keep motion tasteful: animate only transform and opacity (they run on the compositor and stay at 60fps), and respect prefers-reduced-motion — Framer Motion supports both out of the box. Motion should explain the interface, never audition for it.