What the API does
The View Transitions API takes a snapshot of the rendered page, applies a DOM update, takes a second snapshot, and runs a CSS animation between the two. Default behaviour: a 0.25-second cross-fade of the whole page.
Two flavours exist:
- Same-document transitions —
document.startViewTransition(callback). The callback mutates the DOM; the engine handles the before/after snapshots and animates. - Cross-document transitions — opt-in via the
@view-transitionrule plus theview-transition-nameandview-transition-classproperties. Activated automatically on same-origin navigations when both pages opt in.
@view-transition {
navigation: auto;
}
That single rule, on both pages of a navigation, gives a cross-fade between full-page renders. Cross-document support shipped in Chromium 126 (June 2024) and is in development in WebKit and Gecko as of early 2025.
Anatomy of a transition
When startViewTransition() is called, the engine creates a
parallel pseudo-element tree:
::view-transition
└── ::view-transition-group(name)
└── ::view-transition-image-pair(name)
├── ::view-transition-old(name)
└── ::view-transition-new(name)
For each named element (view-transition-name: foo), the engine
takes the old visual rect and the new visual rect, places them in
the pair, and animates between them. Default animation: position,
size, opacity for the group; opacity for the old/new pair.
To customise:
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.4s;
animation-timing-function: cubic-bezier(0.25, 0, 0.3, 1);
}
::view-transition-old(card-hero) {
animation-name: slide-out-left;
}
::view-transition-new(card-hero) {
animation-name: slide-in-right;
}
Naming groups
view-transition-name: <ident> declares which DOM element should
get its own transition group. Anything not named ends up in the
implicit root group.
.card.featured {
view-transition-name: featured-card;
}
.card.featured img {
view-transition-name: featured-image;
}
Names must be unique on a page during the snapshot. Two visible elements sharing a name produces an error and aborts the transition.
Cross-document choreography
For a same-origin navigation:
/* on every page */
@view-transition { navigation: auto; }
/* on detail page */
.hero { view-transition-name: hero; }
/* on list page, the corresponding card */
.card[data-id="42"] .image { view-transition-name: hero; }
When the user clicks the card, the engine matches hero between
old and new pages and slides/scales the image into place. About
60% of the visual polish of a SPA-driven detail-view animation
comes from this single name match.
Accessibility
The API respects prefers-reduced-motion: reduce only if the
author writes the rule. Default animations run regardless. Author
opt-in:
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
animation: none !important;
}
}
About 30% of users on macOS Safari have prefers-reduced-motion
set per Apple’s 2023 accessibility usage report;
the equivalent is rare on Chromium-on-Windows but common on
Chromium-on-ChromeOS.
Common pitfalls
- Two visible elements with the same name. Aborts the
transition. Either uniquify per route or set
view-transition-name: noneon duplicates. - DOM-mutation callback throws. The transition aborts; old and new states are blurred together. Wrap the callback in try/catch and abort cleanly.
- Heavy synchronous DOM work in the callback. The browser blocks rendering until the callback resolves; jank up to the duration of the work. Pre-warm caches; defer non-critical work.
- Cross-document on a slow page. The new page must fully load
before the transition runs; on a 3-second page the
transition feels like a freeze. Pair with the
speculationrulesprefetch hint to warm the new page early.
Cross-engine support
Same-document transitions reached interop in 2024 across Chromium (Blink) 111+, Safari 18 (September 2024), and Firefox in development. Cross-document transitions are Chromium 126+ only as of mid-2024; WebKit and Gecko targets in 2025.
caniuse for view-transition reports about 78% global support for same-document and 60% for cross-document at end of 2024.
Further reading
- CSS View Transitions Module Level 1, w3.org/TR/css-view-transitions-1.
- CSS View Transitions Module Level 2 (cross-document) at drafts.csswg.org/css-view-transitions-2.
- Bramus’s cross-document view transitions explainer is the most thorough author-facing reference.
- Jake Archibald’s 2023 shared element transition demo shows the named-pair pattern at full fidelity.
- Web Platform Tests for view transitions at wpt.fyi/css/css-view-transitions pass at about 92% in Chromium and 71% in WebKit as of late 2024.