Menu

CSS Transition: Property, Duration, Easing and Delay

A CSS transition animates a property from its old value to its new one when it changes, for example on hover. Learn the transition shorthand, every timing function side by side, what can and cannot be transitioned, the height: auto workaround, and reduced motion.

This page includes runnable editors - edit, run, and see output instantly.

A transition in one example

A transition tells the browser: when this property changes, animate it over this much time instead of switching at once. Put it on the element's normal rule, not only on :hover:

Hover the first button: its color fades to green and it rises 4px over 0.4 seconds, and moving the pointer away plays the same transition back. The second button has transition: none and switches instantly. Keyboard users get the same effect through :focus-visible.

The transition shorthand

transition: background-color 0.3s ease-in-out 0.1s;
/*          property         duration timing    delay */
LonghandWhat it setsDefault
transition-propertywhich properties animate (all, or a list)all
transition-durationhow long, in s or ms0s
transition-timing-functionthe speed curveease
transition-delaywait before starting (can be negative)0s

The duration default is 0s, which is why nothing animates until you set one. In the shorthand, the first time is always the duration and the second is the delay. For different settings per property, separate them with commas:

.card {
  transition: transform 0.2s ease-out, box-shadow 0.4s ease-out;
}

Timing functions side by side

The timing function decides how the speed changes during the transition. Press Play and all seven bars move the same distance in the same 1.5 seconds:

Timing functionFeels like
linearconstant speed, mechanical
ease (default)quick start, gentle stop
ease-inslow start, fast end: good for things leaving
ease-outfast start, slow end: good for things arriving
ease-in-outslow at both ends
cubic-bezier(x1, y1, x2, y2)your own curve; a y above 1 overshoots and settles back
steps(n)jumps in n equal steps, no in-between frames

For hover effects and menus, ease-out with a duration between 150ms and 300ms feels responsive.

What can be transitioned

Properties with values in between can be transitioned: colors, lengths (width, padding, margin), opacity, transform, box-shadow, border-radius, filter, background-color. Properties that jump between keywords, such as display or font-family, switch at once.

height: auto is the one people hit most: a panel that opens from height: 0 to height: auto does not animate by default, because the browser does not calculate the values between 0 and "auto". A reliable workaround is a grid wrapper whose single row goes from 0fr to 1fr:

aria-expanded tells screen reader users whether the panel is open, which the animation alone does not.

Running code when a transition ends

The transitionend event fires when a transition finishes, once per property. Use it to do something after the motion, such as moving focus or removing an element:

Respect reduced motion

Some people turn on "reduce motion" in their system settings because movement on screen makes them dizzy or distracts them. Keep color and opacity fades, and drop large movements, with a media query:

@media (prefers-reduced-motion: reduce) {
  .btn { transition: background-color 0.2s ease; } /* no movement, only the color */
}

Keep transitions smooth

transform and opacity are the cheapest properties to animate: the browser can move and fade an element without recalculating the layout. Transitioning width, height, top or margin makes the browser lay out the page again on every frame, which can stutter on slow phones. To move something, prefer transform: translate() over left or margin. The transform page covers the functions.

Common mistakes

  • transition only in the :hover rule. The effect animates in but snaps back when the hover ends. Put transition on the base rule.
  • A duration without a unit. transition: opacity 300 is invalid. Write 300ms or 0.3s.
  • transition: all. It animates every property that changes, including ones you did not mean to animate, and can make layout changes sluggish. List the properties.
  • Expecting display: none to fade. display switches at once. Fade opacity (and set visibility: hidden when the fade ends) instead.
  • Transitioning to height: auto. It jumps. Use the grid-template-rows technique above.
  • Long durations on small interactions. Anything over about 400ms on a button or menu feels slow.

Frequently Asked Questions

How do CSS transitions work?

You declare on an element which properties should animate and for how long, for example transition: background-color 0.3s ease;. When that property's value changes (through :hover, a class, or JavaScript), the browser animates from the old value to the new one instead of switching at once.

What is the order of values in the transition shorthand?

transition: property duration timing-function delay;, for example transition: opacity 0.3s ease-in 0.1s;. The only strict rule is that the first time value is the duration and the second is the delay. Separate several transitions with commas.

Why is my CSS transition not working?

Common causes: the transition is only in the :hover rule (so it animates in and snaps back), the property cannot be animated (display, or height to auto), the duration has no unit (0.3 instead of 0.3s), or the value changes at the same moment the element is added to the page.

Can you transition height: auto?

Not with a plain height transition in every browser: interpolating to auto needs the newer interpolate-size property, which is not supported everywhere yet. Common workarounds are animating grid-template-rows from 0fr to 1fr on a grid wrapper, or animating max-height to a value larger than the content.

What is the difference between transition and animation in CSS?

A transition runs once, between two values, when a property changes. An animation uses @keyframes, can have many steps, starts on its own when the page loads, and can repeat or loop.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED