Making a shadow appear when hovering over a card, shifting a button's color gradually instead of all at once, or sliding a panel off screen: all of these simple animations run on a single property, transition, without a single line of JavaScript.
It turns an otherwise instant style change into a gradual motion spread over a chosen duration, which makes an interface far more pleasant to use than a series of states snapping into place with no visual transition at all.
Definition
transition automatically animates a CSS property moving from one value to another, every time that value changes, whether on hover, on click, or after a class gets added through JavaScript. It relies on four combined settings: the property to animate, the animation's duration, its easing curve, and an optional delay before it starts.
.button {
background-color: #1d4ed8;
transition: background-color 0.3s ease-in-out;
}
.button:hover {
background-color: #1e3a8a;
}The property's four settings
| Setting | Role | Example |
|---|---|---|
transition-property | Property or properties to animate | background-color |
transition-duration | Length of the animation | 0.3s |
transition-timing-function | Easing curve | ease-in-out |
transition-delay | Wait before it starts | 0.1s |
The transition shorthand writes all four values on a single line, in this order: property, duration, curve, delay. The delay is optional and can be left out.
Animating several properties at once
Several properties can be animated at the same time, each with its own settings, by separating the declarations with a comma. Writing transition: all is also possible, animating any property that happens to change, but that shortcut costs more in performance and sometimes animates properties nobody meant to animate. A common example combines transform and box-shadow to lift a card on hover. Our HTML and CSS course builds this kind of card interaction step by step, from the first transition to combining several animated properties together.
.card {
transition:
transform 0.2s ease-out,
box-shadow 0.2s ease-out;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
}The pitfall: two explicit states, not one vague one
transition can only animate the move between two known, calculable values. It fails silently, with no error or warning, the moment one of the two values is auto or depends on content of variable size. A height going from 0 to auto, for instance, never animates smoothly: it snaps instantly, with no visible transition at all.
height: auto with a calculable value, such as max-height set to a large fixed number, or switch to grid-template-rows: 0fr / 1fr, which accepts animation where height: auto consistently fails.transition, animation and will-change
Unlike a CSS animation, transition always needs a triggering event, such as a hover or a class change: it cannot start on its own when the page loads, nor loop indefinitely. The easing curve gets chosen through an Easing and timing function, and on a frequent or expensive animation, will-change can help the browser prepare for it.
Frequently asked questions
transition not trigger when the page loads?Because transition needs a value change to activate: if the property already holds its final value on the very first render, there is nothing to animate. Getting a fade-in effect on load requires setting an initial state in CSS, then switching to the final state with a bit of JavaScript, usually right after the DOM loads.
transition be delayed without delaying its trigger?Yes, that is exactly what the delay setting does: the event that triggers the transition, such as a hover, fires immediately, but the visual motion only starts after the stated delay, which allows several elements to be staggered into a cascading effect.
transition finishes?The transition reverses from its current position, not from the start: the browser simply flips the trajectory from wherever it currently sits, which avoids an abrupt jump and produces natural motion in both directions.