CSS Transitions
Animating a property change smoothly over time instead of having it happen instantly.
2 min de lecture
Without any animation, a CSS property that changes — a color on hover, a size on click — updates instantly, in a single frame. A transition tells the browser to interpolate smoothly between the old and new value instead.
The basic syntax
.button {
background: #2563eb;
transition: background 0.2s ease;
}
.button:hover {
background: #1d4ed8;
}transition is shorthand for transition-property, transition-duration, transition-timing-function, and optionally transition-delay. This rule says: whenever background changes on .button (here, triggered by :hover), animate it over 0.2s using an ease timing curve, rather than snapping instantly.
The transition is declared on the base state (.button), not on :hover — the base rule is what tells the browser "animate changes to this property," and it applies to a change in either direction, hover-in or hover-out.
Transitioning multiple properties
.card {
transform: translateY(0);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
}Comma-separate multiple property duration timing groups to animate several properties, potentially with different durations or curves each. This "lift on hover" pattern — moving an element up slightly with translateY while deepening its shadow — is a common way to signal that a card is interactive.
Timing functions
.a { transition: transform 0.3s linear; }
.b { transition: transform 0.3s ease-in; }
.c { transition: transform 0.3s ease-out; }
.d { transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); }linear moves at a constant rate, which usually feels mechanical for UI. ease-out (fast start, slow finish) tends to feel the most natural for elements entering or responding to interaction, since it mimics real-world deceleration. cubic-bezier() lets you define a fully custom curve — the example above produces a slight "overshoot" bounce, often used for playful pop-in effects.
What can and can't be transitioned
.panel {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.panel.open {
max-height: 500px;
}Only properties with a defined range of intermediate values can be transitioned — colors, lengths, transforms, opacity. Properties like display (which is either none or something else, with nothing in between) can't be smoothly transitioned, which is why the common trick for animating something in and out of existence is max-height (as shown above) or opacity + visibility, rather than transitioning display directly.
Prefer transform and opacity for performance
Animating transform and opacity is significantly cheaper for the browser than animating properties like width, top, or margin, because the former can often be handled by the GPU without forcing the browser to recalculate the page's layout on every frame. Where a design allows it, transform: translateX(...) is a better-performing choice than animating left.