CSS Transitions

A CSS transition animates the change between two states of an element. When a property changes — on hover, on focus, on class change — instead of snapping instantly to the new value, it glides smoothly over a set duration. Transitions make interfaces feel alive and responsive to user actions.

How Transitions Work

DIAGRAM — Without and with transition:

Without transition:
  State A  →  [instant jump]  →  State B

With transition:
  State A  →  [smooth glide over 0.3s]  →  State B
/* State A — normal button */
.btn {
  background: blue;
  transition: background 0.3s ease;
}

/* State B — hovered button */
.btn:hover {
  background: darkblue;
  /* The change from blue to darkblue takes 0.3s */
}

The transition Shorthand

transition: property duration timing-function delay;
PartRequiredDescription
propertyYesWhich CSS property to animate (or all)
durationYesHow long the transition takes (e.g., 0.3s, 200ms)
timing-functionNo (default: ease)The speed curve of the transition
delayNo (default: 0)Wait before starting

Basic Examples

/* Transition one property */
.link {
  color: blue;
  transition: color 0.2s;
}
.link:hover { color: red; }

/* Transition multiple properties */
.card {
  background: white;
  box-shadow: none;
  transition: background 0.3s, box-shadow 0.3s;
}
.card:hover {
  background: #f0f8ff;
  box-shadow: 0 8px 20px rgba(0,0,0,0.15);
}

/* Transition everything */
.btn {
  transition: all 0.25s ease;
}

Avoid transition: all on complex elements. It watches every property for changes, which can cause unexpected transitions and hurt performance. List only the properties you want animated.

Timing Functions — The Speed Curve

The timing function controls the acceleration and deceleration of the transition — how it "feels" in motion.

DIAGRAM — Timing functions:

ease (default):
  slow → fast → slow   ← smooth, natural feeling
  ────────────────────────→

linear:
  constant speed       ← mechanical, robotic feeling
  ────────────────────────→

ease-in:
  slow → fast          ← starts sluggish, accelerates
  ────────────────────────→

ease-out:
  fast → slow          ← starts fast, decelerates (most natural for UI)
  ────────────────────────→

ease-in-out:
  slow → fast → slow   ← symmetric, smooth both ends
  ────────────────────────→
.card {
  transition: transform 0.4s ease-out;
}

.card:hover {
  transform: translateY(-4px);
}

Custom Timing with cubic-bezier()

You can define any curve using four numbers that control two control points of a bezier curve.

/* Bouncy overshoot effect */
.btn {
  transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Snappy, sharp deceleration */
.menu {
  transition: opacity 0.2s cubic-bezier(0.0, 0.0, 0.2, 1);
}

Use tools like easings.net or the Chrome DevTools cubic-bezier editor to visually design timing curves.

Transition Delay

The delay waits before starting the transition. Useful for staggering multiple elements.

.nav-item:nth-child(1) { transition: opacity 0.3s 0s; }
.nav-item:nth-child(2) { transition: opacity 0.3s 0.05s; }
.nav-item:nth-child(3) { transition: opacity 0.3s 0.10s; }
.nav-item:nth-child(4) { transition: opacity 0.3s 0.15s; }
DIAGRAM — Staggered delay:

Item 1: starts at 0s   → fades in first
Item 2: starts at 0.05s → fades in 50ms later
Item 3: starts at 0.10s → fades in 100ms later
Item 4: starts at 0.15s → fades in 150ms later

Creates a cascading entrance effect.

Transitioning Multiple Properties

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

.card:hover {
  transform: translateY(-6px);
  box-shadow: 0 12px 30px rgba(0,0,0,0.15);
  background-color: #f9f9f9;
}

What Can Be Transitioned?

Only properties with numeric or color values can be transitioned — the browser needs two values it can calculate between.

DIAGRAM — Transitionable vs non-transitionable:

✅ CAN transition:
  color, background-color     (color → color)
  opacity                     (0 → 1)
  width, height, padding, margin
  transform (scale, translate, rotate)
  box-shadow, border-color, border-radius
  font-size, line-height
  top, left, right, bottom

❌ CANNOT transition:
  display (block/none — no numeric middle ground)
  visibility → use opacity instead
  font-family, content

Common UI Transition Patterns

Button Press Effect

.btn {
  transform: scale(1);
  transition: transform 0.1s ease-in;
}
.btn:active {
  transform: scale(0.96);
}

Card Lift on Hover

.card {
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  transform: translateY(0);
  transition: box-shadow 0.3s, transform 0.3s;
}
.card:hover {
  box-shadow: 0 12px 24px rgba(0,0,0,0.2);
  transform: translateY(-4px);
}

Fade In on Class Toggle

.modal {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}
.modal.visible {
  opacity: 1;
  pointer-events: auto;
}

Underline Grow on Hover

.nav-link {
  position: relative;
}
.nav-link::after {
  content: "";
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0%;
  height: 2px;
  background: currentColor;
  transition: width 0.3s ease;
}
.nav-link:hover::after {
  width: 100%;
}

Performance — Which Properties to Transition

Browsers animate some properties in the GPU compositor thread — smooth even on slow devices. Others force the browser to recalculate the layout on every frame — expensive.

DIAGRAM — GPU-accelerated vs layout-triggering:

✅ GPU-safe (always prefer these):
  transform: translate, scale, rotate
  opacity

⚠ Layout-triggering (use carefully):
  width, height, top, left, margin, padding
  These cause layout recalculations every frame.

Rule: If you can achieve an effect with transform or opacity,
choose them over geometric properties.

Respecting Reduced Motion

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

This cuts all transitions to near-instant for users who have enabled reduced-motion in their OS settings — an important accessibility consideration.

Transitions are the most low-effort, high-impact CSS technique for making a site feel professional. A 0.2s ease-out on a button or link hover is often the single change that makes a page feel polished instead of flat.

Leave a Comment

Your email address will not be published. Required fields are marked *