Animations
Keyframe animations run on their own — when a page loads, in a loop, or tied to scrolling — and can pass through many intermediate steps. They power loading spinners, attention cues, entrance effects and decorative motion.
Keyframes and the animation property
@keyframes defines the stages of an animation by percentage (from and to mean 0% and 100%). The animation property attaches it to an element with a name and duration, plus optional settings.
Animation properties
| Property | Example | Meaning |
|---|---|---|
animation-name | pulse | Which keyframes |
animation-duration | 1s | One cycle's length |
animation-timing-function | ease-in-out | Speed curve (per keyframe step) |
animation-delay | 0.5s | Wait before starting (negative starts part-way through) |
animation-iteration-count | 3, infinite | How many times |
animation-direction | alternate | Play forwards, backwards, or alternate |
animation-fill-mode | forwards, both | Keep the first/last frame's styles before and after |
animation-play-state | paused | Pause or resume |
A loading spinner
If a keyframe block only has to, the animation starts from the element's current style.
Entrance animations
animation-fill-mode: both (in the shorthand) keeps each item invisible during its delay, then holds the final state. Staggered delays create a cascade.
Alternating and multi-step
An element can run several animations at once, separated by commas. alternate plays forwards then backwards, avoiding a jump at the end of each loop.
Scroll-driven animations
animation-timeline: scroll() links an animation's progress to a scroll position instead of time; view() links it to an element's visibility as it scrolls through the viewport — great for reveal effects. Supported in Chromium-based browsers and Safari, and arriving in Firefox; elsewhere the bar simply stays as its final frame.
Animation vs transition
| Transitions | Animations |
|---|---|
| Triggered by a state change | Run on their own (load, loop, scroll) |
| Two states: from → to | Any number of keyframes |
| Best for hover, focus, toggles | Best for loaders, attention cues, entrances |
Animate responsibly
- Respect
prefers-reduced-motion: turn off or tone down non-essential motion. - Avoid flashing more than three times per second — it can trigger seizures.
- Provide a way to pause long or looping animations.
- Prefer animating
transformandopacityfor smoothness.
@media (prefers-reduced-motion: reduce) {
.balloon,
.heart {
animation: none;
}
}