CSS Animations
A little motion makes a page feel alive. A button that responds when you hover, a card that lifts when you point at it, a spinner that turns while content loads. CSS can do all of this without a line of JavaScript, using two tools: transitions and keyframes.
A transition animates the change between two states. You put transition on the element itself, not on the hover rule, so the browser knows to smooth the change in both directions. When the property changes, the browser interpolates the values frame by frame instead of jumping instantly.
Keyframes describe a full animation with named stages. You write @keyframes, give the animation a name, and list what the element looks like at each step from 0 percent to 100 percent. Then the animation property attaches it and sets the duration, repetition, and easing. Transitions cover small interactions; keyframes cover anything with more than two steps.
Which properties animate well
The browser repaints continuously while an animation runs, so cheap properties matter. transform and opacity are composited on the graphics layer and animate smoothly. Animating width, height, top, or margin forces the browser to recompute layout every frame, which causes jank on weaker phones. Move things with transform: translate, scale, and rotate, and fade with opacity.
.card:hover {
transform: translateY(-4px); /* cheap: no layout recalculation */
}
Keyframes step by step
A keyframe animation has a name and stages. @keyframes bounce declares the name and lists what the element looks like at each point. The animation property attaches it: animation: bounce 1s ease-in-out infinite sets the name, duration, easing, and loop. Between stages the browser interpolates smoothly. Add as many percent stops as you like; the browser draws every frame between them.
@keyframes bounce {
0% { transform: translateY(0); }
50% { transform: translateY(-14px); }
100% { transform: translateY(0); }
}
.ball {
animation: bounce 1s ease-in-out infinite;
}
Respect reduced motion
Some users ask their systems for less motion, and CSS can listen. Wrap looping animations in a media query for prefers-reduced-motion and turn them off or slow them down. It is a small block that makes a big difference for people with motion sensitivity. Motion should support the interface, not decorate it. If an animation has no purpose, the polite choice is to remove it.
@media (prefers-reduced-motion: reduce) {
.ball {
animation: none;
}
}
Syntax
button {
transition: transform 0.2s ease;
}
button:hover {
transform: scale(1.1);
}
Animate transform, Not width/height
Animating width/height triggers layout every frame (jank). Use transform: translate/scale and opacity for smooth 60fps.
.card:hover{transform:translateY(-4px)}
Good to know
- Transitions smooth a change between two states.
- Keyframes handle multi-step animations with named stages.
- Transform and opacity animate cheaply; width and height do not.
- Honor prefers-reduced-motion for users who ask for less motion.