Animations vs. Transitions: What's the Difference?
Before diving in, it's worth clarifying the two main CSS motion tools:
| Feature | Transitions | Animations (@keyframes) |
|---|---|---|
| Trigger | State change (e.g., hover) | Can auto-play or loop |
| Control points | Start and end only | Multiple keyframe stops |
| Looping | No | Yes |
| Complexity | Simple | Complex multi-step motion |
Use transitions for simple, state-driven changes (hover, focus). Use @keyframes animations for anything multi-step, looping, or auto-triggered.
Anatomy of a Keyframe Animation
A CSS animation is made up of two parts: the @keyframes rule (defining the steps) and the animation property (applying it to an element).
@keyframes slide-in {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.card {
animation: slide-in 0.4s ease-out forwards;
}
Using Percentage Steps
You're not limited to from and to. Use percentage values to define complex motion paths:
@keyframes bounce {
0% { transform: translateY(0); }
40% { transform: translateY(-30px); }
60% { transform: translateY(-15px); }
80% { transform: translateY(-5px); }
100% { transform: translateY(0); }
}
Key Animation Properties
- animation-name: The @keyframes rule to use.
- animation-duration: How long one cycle takes (e.g.,
0.5s). - animation-timing-function: Easing curve (
ease,linear,cubic-bezier()). - animation-delay: Wait before starting.
- animation-iteration-count: Number of cycles, or
infinite. - animation-direction:
normal,reverse,alternate. - animation-fill-mode: What styles apply before/after (
forwards,backwards,both).
Performance: Stick to Compositor-Friendly Properties
Not all CSS properties animate equally. For smooth 60fps animations, only animate these properties:
transform(translate, scale, rotate)opacity
Animating width, height, top, left, or background-color forces the browser to recalculate layout or repaint pixels — both expensive operations. Always prefer transform: translateX() over changing left.
Respecting User Preferences
Some users experience discomfort or motion sickness from animations. Always wrap non-essential animations in a media query:
@media (prefers-reduced-motion: no-preference) {
.card {
animation: slide-in 0.4s ease-out forwards;
}
}
This ensures your animations only run for users who haven't opted out of motion in their OS settings.
Staggered Animations with animation-delay
A classic UI pattern is staggering a list of items so they animate in one by one. Use CSS custom properties or nth-child selectors to vary the delay:
.list-item:nth-child(1) { animation-delay: 0s; }
.list-item:nth-child(2) { animation-delay: 0.1s; }
.list-item:nth-child(3) { animation-delay: 0.2s; }
Conclusion
CSS keyframe animations give you expressive control over motion in the browser — without a single line of JavaScript. Master the basics, respect performance constraints, and always keep accessibility in mind. Motion, used thoughtfully, transforms a flat UI into a living, breathing experience.