Skip to main content

CSS Transitions

CSS transitions are the simplest way to add motion to your interfaces. They animate the change between two states — from the current value of a property to a new value — whenever that property changes.

The Transition Property

A transition needs four pieces of information:

.button {
  transition: background-color 0.2s ease-out 0s;
  /*          property         duration timing  delay */
}
  • property — which CSS property to animate
  • duration — how long the transition takes
  • timing-function — the acceleration curve
  • delay — time before the transition starts (optional, defaults to 0)

You can transition multiple properties:

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

Or use all to transition every changing property (use with caution — it can animate properties you did not intend):

.card {
  transition: all 0.2s ease-out;
}

Hover States

The most common use of transitions is smooth hover effects:

Ctrl+Enter
HTML
CSS
JS
Preview

Without the transition, the card would jump to its hover state instantly. With it, the card lifts smoothly upward and its shadow deepens, creating a sense of depth.

Focus States

Transitions also enhance keyboard navigation by making focus indicators feel polished:

Ctrl+Enter
HTML
CSS
JS
Preview

The smooth transition from gray border to blue border with a glowing ring makes focus visible and pleasant.

Timing Functions Deep Dive

Timing functions control the speed curve of a transition. CSS provides built-in keywords and the cubic-bezier() function for custom curves:

Ctrl+Enter
HTML
CSS
JS
Preview

Each keyword maps to a specific cubic-bezier() curve:

Keywordcubic-bezierCharacter
ease(0.25, 0.1, 0.25, 1)General purpose
linear(0, 0, 1, 1)Mechanical, robotic
ease-in(0.42, 0, 1, 1)Accelerating — good for exits
ease-out(0, 0, 0.58, 1)Decelerating — good for entrances
ease-in-out(0.42, 0, 0.58, 1)Smooth — good for position changes

Use tools like cubic-bezier.com to experiment with custom curves visually.

Transition Performance

Not all properties are equal when it comes to performance. Stick to properties that can be hardware-accelerated:

Ctrl+Enter
HTML
CSS
JS
Preview

If you need to animate size changes, use transform: scale() instead of width/height. If you need to animate position, use transform: translate() instead of top/left.

Common Patterns

Button Press Effect

Ctrl+Enter
HTML
CSS
JS
Preview

Fade-In on State Change

Ctrl+Enter
HTML
CSS
JS
Preview

Using visibility alongside opacity ensures the hidden tooltip does not block clicks on elements behind it.

Ctrl+Enter
HTML
CSS
JS
Preview

Expanding Border

Ctrl+Enter
HTML
CSS
JS
Preview

Transition Gotchas

  • You cannot transition display — use opacity and visibility instead, or use the newer transition-behavior: allow-discrete (limited support).
  • You cannot transition auto valuesheight: auto cannot be transitioned. Use max-height with a large value as a workaround, or use CSS Grid's grid-template-rows: 0fr to 1fr trick.
  • Initial page load — transitions can fire on page load if an element starts in a different state. Add a no-transition class that you remove after load if this is a problem.
Ctrl+Enter
HTML
CSS
JS
Preview

This is the cleanest way to animate an element from zero height to its natural content height.