// css · Web Platform Advent #9
The View Transitions API: smooth page and state transitions
Animate between two DOM states with the View Transitions API. startViewTransition, view-transition-name, same-document and cross-document transitions explained.
The View Transitions API animates the change between two states of a page — a list turning into a detail view, a theme toggling, an item being filtered out — with almost no animation code. The browser snapshots the old state, snapshots the new one, and cross-fades (or transforms) between them for you.
Same-document transitions
For state changes inside a single page — a single-page app updating the DOM — wrap the DOM update in document.startViewTransition():
function showDetail(item) {
if (!document.startViewTransition) {
updateDOM(item); // no support: just update, no animation
return;
}
document.startViewTransition(() => updateDOM(item));
} The callback does your normal DOM work. The browser captures a "before" snapshot just before it runs and an "after" snapshot once it finishes, then animates between them. The default is a smooth cross-fade — already a nice upgrade for free.
Customising the animation with CSS
During a transition the browser builds a tree of pseudo-elements you can style. The simplest hook is the root transition group:
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.3s;
} You target the outgoing snapshot with ::view-transition-old() and the incoming one with ::view-transition-new(), then apply any CSS animation you like.
Animating a specific element across states
To make one element appear to move and morph between the two states — a thumbnail growing into a full image — give it a shared view-transition-name in both states:
.hero-image {
view-transition-name: hero;
} The name must be unique on the page at any moment. When the browser finds the same name before and after, it tweens that element's position and size directly instead of cross-fading it, producing a continuous "shared element" effect.
Cross-document transitions (MPA)
Multi-page sites can transition between full page navigations too, with no JavaScript. Opt in from CSS in both pages:
@view-transition {
navigation: auto;
} With that single rule, same-origin navigations animate automatically. Matching view-transition-name values on both pages let an element — say a post's hero image — carry over from the list page to the article page.
Quick reference
| Goal | API |
|---|---|
| SPA state change | document.startViewTransition(cb) |
| MPA navigation | @view-transition { navigation: auto } |
| Style the fade | ::view-transition-old/new(root) |
| Shared element | view-transition-name (unique) |
Support and progressive enhancement
Same-document transitions ship in Chromium browsers and Safari; cross-document support is rolling out and Firefox is implementing both. Because you guard with if (!document.startViewTransition) and the cross-document version is a pure CSS opt-in, the API degrades gracefully: unsupported browsers simply update the page with no animation. That makes it safe to add today as a progressive enhancement.
Reach for view transitions when a jump between states feels abrupt. A small amount of motion gives users a sense of continuity — where things came from and where they went — without you hand-writing a single keyframe in most cases.