transition vs animation
transition animates a change between two states after a trigger, e.g. :hover. animation plays back steps from @keyframes on its own, even in a loop.
Side-by-side comparison
#Needs a trigger (e.g. :hover)
- transition
- Yes, nothing happens without a state change
- animation
- No, it starts on its own once the rule is assigned
Number of steps
- transition
- Two states: starting and ending
- animation
- As many as you like, defined in
@keyframes
Looping
- transition
- Not possible
- animation
- Yes, with
animation-iteration-count: infinite
Starts without user interaction
- transition
- No
- animation
- Yes
Pausing and resuming
- transition
- No
- animation
- Yes, with
animation-play-state
Typical use
- transition
- Hover on buttons, smooth menu openings
- animation
- Spinners, pulsing, loading indicators
Example
#.btn {
background: #7c3aed;
transition: background-color 0.2s;
}
.btn:hover {
background: #6d28d9;
}
.spinner {
animation: spin 1s linear infinite;
}
@keyframes spin {
to { rotate: 360deg; }
}<div class="stage" style="display: flex; gap: 16px; align-items: center;">
<button class="btn" type="button" style="padding: 8px 16px; border: 0; border-radius: 8px; color: #fff;">Hover over me</button>
<div class="spinner" style="width: 28px; height: 28px; border: 3px solid #333; border-top-color: #a78bfa; border-radius: 50%;"></div>
</div>Definition and usage
#The transition property needs a trigger: a state change, for example :hover, a class added by JavaScript, or a change in a @media query. It only interpolates between two values, the one before the change and the one after it, and plays once per change.
The animation property relies on an @keyframes rule, where you describe as many steps as you like at different percentages of the timeline. It starts on its own, right after the rule is assigned to an element, with no user interaction at all. Thanks to animation-iteration-count it can loop, and animation-direction and animation-play-state give you control over direction and pausing.
In practice, transition is enough for simple interface effects: highlighting a button, opening a menu, changing color on focus. animation works well where motion needs to happen on its own, without end: loading spinners, pulsing badges, welcome entrance effects for elements on the page.
Syntax
#transition: <property> <duration> <timing-function>? <delay>?;
animation: <keyframes-name> <duration> <timing-function>? <delay>? <iteration-count>?;More examples
#@keyframes pulse {
50% { transform: scale(1.15); }
}
.badge {
animation: pulse 1.2s ease-in-out infinite;
}<span class="box badge" style="display: inline-grid;">New</span>There’s nothing to click or hover: the animation starts right away once the page loads.
.card {
transform: scale(1);
transition: transform 0.3s;
}<div class="box" style="width: 220px;">Waiting for a state change, e.g. :hover</div>On its own, transition doesn’t animate anything. It needs a second rule, e.g. :hover, that changes the transform value.
Good practices
#- If something needs to happen without user involvement and in a loop, reach for
animation. transitionis simpler and lighter for hover or focus effects on one or two properties.- You can combine them: an entrance animation with
@keyframes, thentransitionon:hoverfor the same element.
Spotted a mistake or missing an example? Write to us.