← Back to CSS3 Mastery
Intermediate13 min read

Transitions & Transforms

Add smooth motion to your interfaces with CSS transitions and transforms — animate property changes, move elements in 2D and 3D space, and respect user motion preferences.

CSS Transitions

Transitions animate property changes over time. Specify the property (or use all with caution), duration, timing function, and optional delay. Only animatable properties can transition — colors, opacity, transforms, and dimensions work; display does not.

Always transition specific properties rather than all to avoid performance issues and unexpected animations on unrelated property changes.

  • Prefer transform and opacity for 60fps animations — they skip layout
  • Use transition-behavior: allow-discrete for display transitions in modern CSS
  • Keep durations under 400ms for UI feedback; 200–300ms is the sweet spot
.button {
  background: #2563eb;
  transform: translateY(0);
  transition: background 200ms ease, transform 200ms ease;
}
.button:hover {
  background: #1d4ed8;
  transform: translateY(-2px);
}

Transform Functions

Transforms modify an element visual appearance without affecting document flow. Translate moves elements, rotate spins them, scale resizes them, and skew slants them. Transforms can be chained and are GPU-accelerated.

Use transform instead of top/left for animations because transforms do not trigger layout recalculation. This keeps animations smooth even on lower-end devices.

.card:hover {
  transform: scale(1.02) translateY(-4px);
}
.icon-expand {
  transform: rotate(0deg);
  transition: transform 300ms ease;
}
.icon-expand.open {
  transform: rotate(180deg);
}

Transform Origin

Transform-origin sets the pivot point for transforms. The default is center (50% 50%). Changing origin affects how rotate and scale appear — a scale from bottom-left looks like an element growing upward.

For dropdown menus and accordions, setting transform-origin: top matches the natural expansion direction and makes animations feel intentional.

.dropdown-menu {
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 200ms ease;
}
.dropdown-menu.open {
  transform: scaleY(1);
}

Timing Functions

Easing curves control animation acceleration. ease starts slow, speeds up, then slows down. ease-in-out is symmetric. Linear is constant speed — good for progress bars, bad for UI elements.

Custom cubic-bezier values create personality. A curve like cubic-bezier(0.34, 1.56, 0.64, 1) adds a subtle bounce. Use DevTools easing editor to preview curves interactively.

  • ease-out feels best for elements entering the screen
  • ease-in feels best for elements leaving
  • Use steps() for frame-by-frame or typewriter effects
.modal-enter {
  transition: opacity 250ms cubic-bezier(0.16, 1, 0.3, 1),
              transform 250ms cubic-bezier(0.16, 1, 0.3, 1);
  opacity: 0;
  transform: scale(0.95);
}
.modal-enter.active {
  opacity: 1;
  transform: scale(1);
}

Reduced Motion

Always respect prefers-reduced-motion for users with vestibular disorders. Wrap animations in a media query that disables or simplifies motion when the preference is set.

Reduced motion does not mean no motion — it means replacing spatial movement with opacity fades or instant state changes.

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Get In Touch


Ready to discuss your next project? Drop me a message.