The CSS transition property
The CSS transition property smoothly animates a value when it changes — say a color on hover — instead of snapping instantly. The shorthand is property duration timing-function delay, e.g. transition: background-color 0.2s ease. Put it on the element's normal state, not the hover state, so it eases both in and out.
Overview
A transition tells the browser to animate a property from its old value to its new one over a set time, rather than flipping instantly. Change a button's background on hover and, with a transition, it fades smoothly; without one, it jumps.
The shorthand takes four parts: which property to animate, how long it takes, the easing curve, and an optional delay. transition: background-color 0.2s ease covers the common case. You can animate several properties at once by listing them comma-separated, or use the keyword all to animate every property that changes — though naming the properties is usually better for performance and predictability.
The detail people get wrong: put the transition on the element's default state, not on :hover. Declaring it on the base rule means the animation runs both when the hover begins and when it ends, so the effect eases away as smoothly as it arrives. For the smoothest results, animate transform and opacity rather than layout properties.
Syntax
selector {
transition: property duration timing-function delay;
}
/* fade the background on hover */
.btn {
transition: background-color 0.2s ease;
}
.btn:hover {
background-color: #1c7ce9;
}
Values
The transition property accepts the values below. Every property also accepts the CSS-wide keywords inherit, initial, revert and unset.
| Value | Description |
|---|---|
property |
The property to animate, e.g. background-color, transform, or all. |
duration |
How long it takes, e.g. 0.2s or 200ms. Required for anything to happen. |
timing-function |
The easing curve: ease, linear, ease-in-out, or a cubic-bezier(). |
delay |
An optional wait before it starts, e.g. 0.1s. |
multiple |
Comma-separate to animate several properties: color 0.2s, transform 0.3s. |
Example
<style>
.btn {
transition: background-color 0.25s ease, transform 0.25s ease;
background: #1c7ce9;
color: #fff;
border: 0;
padding: 12px 22px;
border-radius: 8px;
font: 600 15px system-ui, sans-serif;
cursor: pointer;
}
.btn:hover {
background: #0f5fc2;
transform: translateY(-2px);
}
</style>
<button class="btn">Hover me — I ease, not snap</button>
Best practices
- Declare the transition on the base rule, not on
:hover, so the change eases both ways. - Animate transform and opacity for smooth, GPU-friendly motion; avoid transitioning width, height or top/left.
- Name the properties you want to animate rather than using
all— it is faster and avoids animating things by accident. - Keep durations short (around 150–300ms) for UI feedback; anything slower starts to feel sluggish.
Accessibility
Motion is not free for everyone — vestibular conditions mean some people feel unwell when the screen moves. Respect the prefers-reduced-motion setting: wrap non-essential animation in @media (prefers-reduced-motion: no-preference), or add a reduce block that cuts durations to near zero, so users who have asked for less motion get a calm, instant interface.
Transitions should also never be the only way information is conveyed. A color fade that signals success still needs a label or icon behind it, and a control should be fully usable before, during and after its animation.
Frequently asked questions
How do I add a hover transition in CSS?
.btn { transition: background-color 0.2s ease; }, then change the property on :hover. The change then fades in and out.Why is my transition not working?
duration (a transition needs a time to run over) or putting the transition on the :hover state instead of the base state. Also, not every property can be animated.What is the difference between transition and animation?
transition animates between two states when a value changes, like on hover. A CSS animation with @keyframes can run on its own, loop, and define many steps in between.How do I respect reduced motion preferences?
@media (prefers-reduced-motion: no-preference), or add a reduce block that shortens or removes the transition, so people who prefer less motion are not forced to see it.