The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Start a transitiondocument.startViewTransition(() => updateDOM());View examples
Provide an API fallbackdocument.startViewTransition ? document.startViewTransition(update) : update();View examples
Name a shared element.hero { view-transition-name: product-hero; }View examples
Exclude an element.live-clock { view-transition-name: none; }View examples
Style group geometry::view-transition-group(product-hero) { animation-duration: 360ms; }View examples
Animate the old capture::view-transition-old(product-hero) { animation: fade-out 180ms ease-in both; }View examples
Animate the new capture::view-transition-new(product-hero) { animation: fade-in 240ms ease-out both; }View examples
Customize the root cross-fade::view-transition-old(root) { animation: fade-out 160ms linear both; }View examples
Control image-pair blending::view-transition-image-pair(card) { isolation: isolate; }View examples
Opt in navigation@view-transition { navigation: auto; }View examples
Declare navigation types@view-transition { navigation: auto; types: forwards backwards; }View examples
Match an active type:active-view-transition-type(forwards) { --slide-direction: 1; }View examples
Class several captures.tile { view-transition-class: tile; }View examples
Style a capture class::view-transition-group(*.tile) { animation-duration: 300ms; }View examples
Respect reduced motion@media (prefers-reduced-motion: reduce) { ::view-transition-group(*) { animation-duration: 1ms; }; }View examples
Limit expensive capture area.card { contain: paint; view-transition-name: card; }View examples

View transitions separate an immediate document-state change from an optional animated rendering of that change. The browser captures old and new visual states into generated pseudo-elements, while the real DOM moves directly to its correct state. Use the API as progressive enhancement, assign unique names only to meaningful shared elements, keep the update callback focused on DOM state, and disable nonessential motion when the user requests reduced motion. Cross-document features and Level 2 selectors remain evolving, so test current target browsers.

Step by step

Detailed examples

01

Wrap a same-document state change, not application logic

document.startViewTransition(updateCallback) captures the old state, invokes the callback, captures the new state, and animates between them. The callback may be asynchronous, but rendering waits for it, so complete only the state update required for the next visual state. Feature-detect the method and always execute the update without animation when it is absent or a transition is skipped.

Progressively animate a layout toggle
const button = document.querySelector('[data-layout-toggle]');

button.addEventListener('click', () => {
  const update = () => document.body.classList.toggle('compact');

  if (document.startViewTransition) {
    document.startViewTransition(update);
  } else {
    update();
  }
});
Back to quick reference ↑
02

Capture shared elements under unique names

The root document transitions by default. Assign view-transition-name only when an element needs independent geometry or animation. During one captured state, each custom name must resolve to at most one rendered element or the transition is skipped. Keep names stable across old and new states, and do not use captures to hide incorrect focus order or DOM semantics.

Track a product image and heading separately
.product__image { view-transition-name: product-hero; }
.product__title { view-transition-name: product-title; }
.live-clock { view-transition-name: none; }

::view-transition-group(product-hero) {
  animation-duration: 360ms;
  animation-timing-function: cubic-bezier(.2, .8, .2, 1);
}
Back to quick reference ↑
03

Target the generated transition tree deliberately

Each named capture creates a group, image-pair, old, and new pseudo-element. The group interpolates layout geometry; old and new carry captured imagery and default cross-fade animations. Style the narrowest level that expresses the effect, and account for cases where only old or only new exists because an element is entering or leaving.

Give entering and leaving states distinct motion
::view-transition-old(product-hero) {
  animation: hero-leave 180ms ease-in both;
}
::view-transition-new(product-hero) {
  animation: hero-enter 280ms ease-out both;
}

@keyframes hero-leave { to { opacity: 0; scale: .96; } }
@keyframes hero-enter { from { opacity: 0; scale: 1.04; } }
Back to quick reference ↑
04

Customize timing without fighting the capture model

Animation timing set on a group inherits through the generated tree in the user-agent styles. Replace old and new animations together when you need a custom cross-fade, and retain fill modes so captures do not flash at their endpoints. The transition layer paints above ordinary page content, so avoid long-running or interaction-blocking effects.

Replace the root transition with a short fade
::view-transition-image-pair(root) { isolation: isolate; }
::view-transition-old(root) { animation: fade-out 160ms linear both; }
::view-transition-new(root) { animation: fade-in 220ms linear both; }

@keyframes fade-out { to { opacity: 0; } }
@keyframes fade-in { from { opacity: 0; } }
Back to quick reference ↑
05

Opt both documents into eligible navigations

Level 2's @view-transition rule enables transitions for eligible user-initiated same-origin navigations when both old and new documents opt in. Reloads, address-bar navigations, cross-origin redirects, and hidden pages may not transition. The types descriptor and :active-view-transition-type() enable direction-specific styles, but navigation itself must never depend on animation support.

Opt in and conditionally reverse motion
@view-transition {
  navigation: auto;
  types: forwards backwards;
}

:root:active-view-transition-type(forwards) { --travel: 2rem; }
:root:active-view-transition-type(backwards) { --travel: -2rem; }

::view-transition-new(root) {
  animation: enter 240ms ease-out both;
}
@keyframes enter { from { opacity: 0; translate: var(--travel, 0) 0; } }
Back to quick reference ↑
06

Share pseudo-element styles across many captures

Level 2 view-transition-class works like a styling class for generated transition pseudo-elements, but it does not capture an element by itself. Each element still needs a unique view-transition-name. The *.class selector form avoids repeating identical group rules across a collection whose items transition independently.

Apply one duration to independently named tiles
#tile-a { view-transition-name: tile-a; }
#tile-b { view-transition-name: tile-b; }
.tile { view-transition-class: tile; }

::view-transition-group(*.tile) {
  animation-duration: 300ms;
  animation-timing-function: ease-out;
}
Back to quick reference ↑
07

Preserve user control, focus, and rendering performance

A transition is visual enhancement, not a substitute for correct focus management, live-region behavior, or navigation feedback. Reduce or eliminate nonessential animation under prefers-reduced-motion. Capture only elements that materially improve continuity; large named subtrees consume memory, and filters, blending, or many simultaneous captures increase rendering cost.

Offer a near-instant reduced-motion path
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation-duration: 1ms;
    animation-delay: 0s;
  }
}

.product-card { contain: paint; }
Back to quick reference ↑

Local code tester

Prepare shared elements for view transitions

Inspect the named capture rules and reduced-motion guard; animation requires an eligible state change or navigation.

Runs in your browser
Preview

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. World Wide Web ConsortiumCSS View Transitions Module Level 1w3.org
  2. World Wide Web ConsortiumCSS View Transitions Module Level 2w3.org
  3. World Wide Web ConsortiumCSS Animations Level 1w3.org
  4. WHATWGHTML Living Standard: View transitionshtml.spec.whatwg.org

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback