CSS: Transitions

Smoothly animate changes between CSS property values.

transition-property

transition-property specifies which CSS property should be animated when it changes. Setting it to all transitions every property that changes, but targeting a specific property is more performant.

transition-property

Always place transition on the base element rule, not the :hover rule. If you place it on :hover, the transition only plays going in, not coming back.

  • transition-property: background-color: only animate the background colour
  • transition-property: all: animate every property that changes (use with caution)
  • transition-property: none: disables transitions
  • Place transition on the base element, not on :hover
  • Only properties with numeric or colour values can be transitioned, display cannot be transitioned

transition-property

Only the background-color transitions, other properties change instantly.

transition-duration

transition-duration sets how long the transition takes to complete. Values are in seconds (s) or milliseconds (ms). Without a duration, transitions are instant.

transition-duration

Most UI transitions should be between 150ms and 400ms. Too short feels abrupt; too long feels sluggish. 200–300ms is the sweet spot for hover effects.

  • 0.2s or 200ms: fast; good for small hover effects like colour changes
  • 0.3s or 300ms: medium; good for button and card interactions
  • 0.5s or 500ms: slow; good for modals or page-level transitions
  • 1s is usually too slow for interactive UI elements
  • Both s and ms units are valid: 0.3s and 300ms are identical

transition-duration

Hover each box to see how duration affects the speed of the transition.

transition-timing-function

transition-timing-function controls the speed curve of the transition: how the animation accelerates and decelerates over its duration.

transition-timing-function

The timing function shapes how the transition feels. ease is the most natural for most UI interactions; linear is best for continuous loops like spinners.

  • ease: slow start, fast middle, slow end (default)
  • linear: constant speed from start to finish
  • ease-in: starts slow, ends fast
  • ease-out: starts fast, ends slow (feels most natural for hover-out)
  • ease-in-out: slow start and end, fast middle (symmetric)
  • cubic-bezier(x1,y1,x2,y2): define a custom curve for precise control

timing functions

Hover the container to see how each timing function moves the ball differently.

transition-delay

transition-delay sets a waiting period before the transition starts. The property changes immediately in the browser's internal state: only the visual animation is delayed.

transition-delay

transition-delay is useful for staggering multiple elements so they animate one after another. A negative delay starts the animation partway through.

  • transition-delay: 0.2s: wait 200ms before the transition begins
  • transition-delay: 0s: no delay, transition starts immediately (default)
  • negative delay: e.g. -0.1s starts the animation already 100ms in
  • Stagger items by giving each a slightly larger delay to create a cascade effect

transition-delay

Hover the container, each item starts its transition slightly later, creating a stagger effect.

Transition Shorthand

The transition shorthand combines all four transition properties in one declaration. The order is: property duration timing-function delay.

transition shorthand

The shorthand is the most common way to write transitions. Only property and duration are required: timing-function defaults to ease and delay defaults to 0s.

  • transition: background-color 0.3s: property and duration only (timing defaults to ease)
  • transition: background-color 0.3s ease-out: with timing function
  • transition: background-color 0.3s ease-out 0.1s: with delay
  • transition: all 0.3s ease: transitions every changing property

transition shorthand

All transition properties written in a single declaration.

Animating Multiple Properties

You can transition multiple properties at once by separating them with commas. Each property can have its own duration, timing function, and delay.

Multiple transitions

Use a comma-separated list to give each property its own transition settings. This is more precise and performant than transition: all.

  • Separate multiple transitions with commas
  • transition: background 0.3s, transform 0.2s: background takes 0.3s, transform takes 0.2s
  • Each property can have a different duration, timing, and delay
  • Avoid transition: all in production, it can accidentally animate properties you did not intend

Multiple properties

Background, transform, and box-shadow each transition at their own speed.

Performance Considerations

Not all CSS properties are equal when it comes to animation performance. Transitioning the wrong properties can cause the browser to recalculate the layout on every frame, leading to jank and dropped frames.

Performance: use transform and opacity

The browser rendering pipeline has three stages: layout, paint, and composite. Only transform and opacity run entirely in the composite stage, making them GPU-accelerated and smooth.

  • transform and opacity: GPU-accelerated; do not trigger layout or paint; always 60fps
  • color, background-color, box-shadow: trigger repaint only; acceptable for most UI
  • width, height, top, left, margin, padding: trigger full layout recalculation on every frame; avoid animating these
  • Use transform: translateX() instead of left/right to move elements
  • Use transform: scale() instead of width/height to resize elements
  • will-change: transform: hints to the browser to promote the element to its own GPU layer in advance

Performance

Both visually expand on hover, but only the second is GPU-accelerated.

Common Transition Patterns

These patterns appear in almost every project. They are simple but make a significant difference in how polished and interactive a UI feels.

Common Patterns

These are the most frequently used transition recipes. Each one targets GPU-friendly properties for smooth performance.

  • Button lift: transform: translateY(-2px) + increased box-shadow on :hover
  • Fade in/out: opacity: 0 to opacity: 1 with transition: opacity 0.3s
  • Colour swap: transition: background-color 0.2s, color 0.2s on links and buttons
  • Grow on hover: transform: scale(1.05) on cards or images
  • Slide in: transform: translateX(-100%) to translateX(0) for drawers and menus

Card lift pattern

Card lifts and casts a deeper shadow on hover, a common card interaction.

Fade with opacity

Element fades out on hover using opacity transition.

Knowledge Check

1. Where should the transition property be placed?

2. What does transition-duration: 0.3s mean?

3. Which timing function starts slow, speeds up, then slows down at the end?

4. What does transition-property: all do?

5. Why are transform and opacity preferred for transitions over top/left or width?

6. What does transition-delay: 0.2s do?