Transitions That Feel Right

Choose easing deliberately, animate only cheap properties, and respect users who prefer reduced motion.

A transition is easy to write and easy to write badly. The difference between an interface that feels premium and one that feels janky is almost entirely in the details of your transitions.

Name your properties

transition: all 0.3s is tempting and wrong. It forces the browser to watch every property for change, and it'll happily animate things you never intended. List exactly what should move:

transition: transform .3s ease, opacity .3s ease;

Easing is emotion

  • ease-out — fast then slow. Best for things entering or responding to the user; feels snappy.
  • ease-in — slow then fast. Good for things leaving.
  • cubic-bezier(...) — roll your own curve for personality, including gentle overshoot.

Only animate cheap properties

Animate transform and opacity. They run on the GPU and don't trigger layout. Animating width, height, top, or margin forces the browser to recalculate layout every frame — that's where jank comes from.

Example

Try it yourself
Loading editor…
Press Run to see the result.

When to use it

  • A developer uses transition: transform 0.2s cubic-bezier(0.34,1.56,0.64,1) for a button to give a springy bounce feel on hover.
  • A developer adds @media (prefers-reduced-motion: reduce) { * { transition: none !important; } } to respect users who disable animations for accessibility.
  • A designer restricts animated properties to transform and opacity only so all transitions run on the compositor thread and never drop frames.

More examples

Easing functions compared

Compares ease, linear, and a custom spring-like cubic-bezier so the same scale transform feels completely different.

Example Β· css
.btn-ease    { transition: transform 0.3s ease; }
.btn-linear  { transition: transform 0.3s linear; }
.btn-spring  {
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.btn:hover { transform: scale(1.08); }

Compositor-friendly transitions

Limits transitions to transform and opacity which run on the GPU compositor, avoiding expensive layout recalculations.

Example Β· css
/* Fast: composited on GPU, no reflow */
.fast {
  transition: transform 0.25s ease, opacity 0.25s ease;
}

/* Slow: triggers layout recalculation */
/* .avoid { transition: width 0.25s, height 0.25s; } */

Respecting reduced motion

Provides a smooth hover animation by default but disables motion for users who have opted into reduced-motion mode.

Example Β· css
.card {
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.card:hover {
  transform: translateY(-6px);
}

@media (prefers-reduced-motion: reduce) {
  .card { transition: none; }
  .card:hover { transform: none; }
}

Discussion

  • Be the first to comment on this lesson.
Transitions That Feel Right β€” CSS | SoundsCode