Mar 2025

View Transitions

document.startViewTransition() wraps a state update. Elements with matching view-transition-name values morph between their old and new positions automatically. The browser generates ::view-transition-old and ::view-transition-new pseudo-elements, animating between them with a cross-fade by default. Custom keyframes override the default.

View Transitions

view transitions
Spring physics
Verlet integration
OKLCH color
Perceptual space
Fluid type
CSS clamp()

The View Transitions API lets the browser animate between two DOM states with a screenshot-and-crossfade mechanism. This demo drives a list-to-detail navigation: clicking a row transitions the entire panel, with named elements morphing between states.

How the API works

document.startViewTransition(() => {
  // Mutate DOM state here
  setState(newState);
});

The browser takes a screenshot before the callback runs, then a second screenshot after. It renders both as pseudo-elements — ::view-transition-old(root) and ::view-transition-new(root) — and plays a crossfade between them. The duration and easing are fully customizable with CSS.

Named transitions

Elements can opt into independent animations via view-transition-name. When both the old and new DOM have an element with the same name, the browser morphs between them with a shared-element transition rather than a full-page crossfade.

/* The element moves and resizes between states */
.list-item { view-transition-name: vt-item-1; }
.detail-view { view-transition-name: vt-item-1; }

The demo assigns names dynamically based on item id, so each row has its own named transition.

Progressive enhancement

The API is wrapped in a feature check:

if ("startViewTransition" in document) {
  document.startViewTransition(update);
} else {
  update();
}

Browsers without the API still navigate — they just don't animate. No polyfill needed.