Build motion by watching it
Writing keyframes blind means saving, reloading and squinting. Here you add stops at percentages, set transforms and opacity at each one, and press play. Pause it, scrub it, adjust and copy the finished animation CSS.
It's a good way to learn how @keyframes behave, and a fast way to build a loader, a fade-in or a bounce.
Animations versus transitions
A transition moves between two states when something changes, like a hover. An animation runs on its own timeline with as many stops as you like and can loop. Use transitions for simple state changes. Use animations for anything with more than two steps, or anything that starts by itself.
Run once, loop or pause
animation-iteration-count: 1 plays it once on load. Use infinite for loops. To pause on hover, set animation-play-state: paused on the :hover rule. To start several animations together, give them the same duration and no delay, or the same delay if you want them staggered.
Keep it fast and kind
Animate transform and opacity. They run on the GPU and rarely cause layout work. Animating width, height or top forces the browser to recalculate layout every frame, and it shows on cheap phones.
Good motion is quick and has a purpose. 150 to 300 milliseconds suits most interface changes. And respect people who've turned on reduced motion. Wrap decorative animation in a prefers-reduced-motion check.
Browser support
CSS animations work in every current desktop and mobile browser. No prefixes are needed. Your work stays in your browser.
Keyframes in plain terms
A keyframe animation is a list of states with percentages. At 0 percent the box is here. At 50 percent it's over there. At 100 percent it's back. The browser fills in everything between. You name the animation, set a duration and attach it to an element.
Stick to transform and opacity where you can. Those two properties are cheap for the browser and keep animation smooth. Animating width, height, top or left forces layout work and can stutter on low-end phones.
Use the builder to scrub the timeline, tweak stops and copy the finished code.
Timing and feel
Duration and easing do more for the feel than the movement itself. A fade of 200 milliseconds feels crisp. The same fade at a second feels sluggish. Ease-out suits things arriving, ease-in suits things leaving.
Loops and delays deserve restraint. A constant bouncing icon wears people down. If an animation repeats, give it a purpose and let it pause.
Finally, respect people who ask for less motion. Wrap decorative animation in a prefers-reduced-motion check so those users get a calm page.
- Animate transform and opacity first
- Keep most UI motion between 150 and 300 ms
- Use ease-out for entrances
- Honor reduced-motion settings
Debugging a stuck animation
If nothing moves, check the animation name matches the keyframes name exactly and that duration isn't zero. If it jumps at the end, set animation-fill-mode to forwards. If it restarts oddly, check you aren't toggling the class twice.
Use the browser's animation panel to slow playback and scrub frames. It beats guessing.
Respect prefers-reduced-motion. Wrap non-essential movement in a media query that turns it off, and provide a static state.