CSS animation is a way to move or restyle an element through several steps defined in an @keyframes rule, without JavaScript. It is specified in the W3C CSS Animations Level 1, and it starts by itself when the animation-name is applied. The detail people look up most is that animation-iteration-count defaults to 1 and infinite repeats forever.
How it works
You write an @keyframes block that names the states, then attach it to an element with animation properties. Unlike a transition, no change of state is needed to begin. The animation starts as soon as the element is styled with the name.
- animation-name: the @keyframes identifier to run.
- animation-duration: length of one iteration.
- animation-timing-function: easing applied between keyframes.
- animation-delay: wait before the first iteration.
- animation-iteration-count: how many times to run. The initial value is 1, and infinite repeats forever.
- animation-direction: normal, reverse, alternate or alternate-reverse.
- animation-fill-mode: none, forwards, backwards or both. It decides what shows before the start and after the end.
- animation-play-state: running (initial) or paused.
The shorthand below uses a 1s delay, 2s duration and 3 alternating iterations:
@keyframes slide { from { margin-left: 0 } to { margin-left: 100px } }
#an { animation: slide 2s linear 1s 3 alternate both; }
Read back with element.getAnimations()[0].effect.getComputedTiming() in headless Chromium 141:
name: slide delay: 1000 duration: 2000 iterations: 3
direction: alternate fill: both endTime: 7000
The end time is 7000 ms: 1000 ms of delay plus 3 iterations of 2000 ms. Delay is counted once, not per iteration.
What is the order of values in the animation shorthand?
The first time value is the duration and the second is the delay, and the other keywords can come in any order. So 3s 1s means a 3 second duration after a 1 second wait.
Common pitfalls
- Snap-back at the end: with the default fill-mode of none, the element returns to its normal style when the animation finishes. Use forwards to hold the last frame.
- A delay with no fill: during animation-delay the element shows its normal style, not the first keyframe. Use backwards or both to show the from state early.
- Animating non-interpolable properties: a custom property without a registered type changes in a single step. Register it with @property and a syntax such as angle to get smooth values.
- Ignoring reduced motion: users can ask for less motion. In a test with reduced motion emulated, prefers-reduced-motion: reduce matched and no-preference did not. Wrap large motion in a media query.
- Animating layout properties: margin, width and top force layout each frame. Prefer transform and opacity for smooth results.
- Duplicate names: if two @keyframes rules share a name, the last one in document order is used and the earlier ones are ignored.
Related terms
- CSS transition — two-state change that needs a trigger instead of keyframes
- CSS transform — the property most animations drive
- CSS cascade — decides which @keyframes and animation declarations apply
- CSS custom properties — can be registered and animated with @property
See also