CSS transitions let a property change smoothly over time instead of jumping instantly from one value to another. Hover a button and its color snaps from blue to dark blue instantly — that's a jarring, cheap-feeling interaction. Add a transition, and that same color change eases over a fraction of a second, which is often all it takes to make an interface feel polished rather than static.

The transition Property

The transition shorthand takes up to four values: which property to animate, how long it takes, the easing curve, and an optional delay.

.button {
  background: #2563eb;
  color: white;
  padding: 10px 20px;
  border-radius: 8px;
  transform: scale(1);
  transition: background 0.2s ease, transform 0.2s ease;
}

.button:hover {
  background: #1d4ed8;
  transform: scale(1.05);
}
<button class="button">Click Me</button>

This renders a blue button that smoothly darkens and grows slightly larger over 0.2 seconds whenever the mouse hovers over it, instead of abruptly changing. Notice the transition is declared on the base .button class, not on :hover — this matters, because it means the transition applies both when the hover starts and when it ends, so the button eases back to normal just as smoothly when the mouse leaves.

transition-timing-function

The timing function controls the pace of the change, not just its duration. A few you'll use constantly:

transition-timing-function: ease;        /* default — starts slow, speeds up, ends slow */
transition-timing-function: linear;      /* constant speed throughout */
transition-timing-function: ease-in;     /* starts slow, finishes fast */
transition-timing-function: ease-out;    /* starts fast, finishes slow — feels snappy */

ease-out tends to feel the most natural for UI feedback (like a hover or a menu opening) because real-world motion rarely stops abruptly — things decelerate as they settle. linear is best reserved for things like a continuously spinning loading icon, which is more naturally handled with an animation instead of a transition.

Transitioning Multiple Properties, and What You Can't Transition

You can comma-separate multiple properties to transition them with different timings, as shown in the button example above (background and transform both get their own 0.2s). You can also use transition: all 0.2s ease; to transition every animatable property that changes — convenient, but it's a performance trap if you're not careful, since the browser then has to watch every property for changes rather than just the ones you actually intend to animate.

Not everything can be transitioned smoothly. Properties like display are binary (an element is either in the layout or not) and simply snap between states — there's no "half displayed" state for the browser to interpolate through. For that kind of effect, you typically transition opacity and visibility together instead of toggling display directly.

A practical rule of thumb: reach for a transition whenever a change is triggered by a specific event (hover, focus, a class being toggled) and only needs to happen once per trigger. Reach for a full @keyframes animation when you need something that loops, has multiple distinct steps, or needs to start automatically without any trigger at all.