While transitions animate between two states, keyframe animations let you define complex, multi-step sequences. They can run automatically, repeat indefinitely, and create effects that transitions simply cannot.
The @keyframes Syntax
Define an animation sequence with @keyframes, then apply it with the animation property:
For multi-step animations, use percentage keyframes:
You can list multiple stops at the same percentage to hold a value:
Animation Properties
The animation shorthand combines multiple properties:
.element {
animation: bounce 0.6s ease-in-out 0.2s infinite alternate both;
/* name duration timing delay count direction fill */
}Here is what each property controls:
| Property | Values | Purpose |
|---|---|---|
animation-name | keyframe name | Which animation to run |
animation-duration | time (e.g., 0.3s) | How long one cycle takes |
animation-timing-function | ease, linear, cubic-bezier | Speed curve |
animation-delay | time | Wait before starting |
animation-iteration-count | number or infinite | How many times to repeat |
animation-direction | normal, reverse, alternate | Direction of playback |
animation-fill-mode | none, forwards, backwards, both | What styles apply before/after |
animation-play-state | running, paused | Play or pause |
Fill Modes
Fill mode is critical for one-shot animations. Without it, the element snaps back to its original state when the animation ends:
Use forwards when the animation should stick. Use both when there is a delay and the element should start in the first keyframe state.
Practical Animations
Loading Spinner
Skeleton Screen Shimmer
Staggered List Entry
Staggering creates a cascading effect that feels natural and draws the eye down the list. Keep delays short (30-80ms between items) to avoid feeling sluggish.
Notification Entry
The slight overshoot at 60% creates a natural deceleration that catches the user's eye.
Choreography
When multiple elements animate, their timing relationships matter. Choreography is the art of making multiple animations feel coordinated:
Rules for good choreography:
- Container before content — the backdrop or wrapper should appear before its children
- Large movements before small ones — primary elements animate first
- Keep total sequence under 500ms — users should not wait for animations to finish
- Exit animations are faster than entries — when closing, users want it gone quickly
Reducing Motion
Always provide a reduced-motion alternative:
This global reset disables all animations for users who request it while still allowing animation-fill-mode: forwards to apply final states instantly.