Basic Cross-Fade with the View Transitions API

Wrap any DOM mutation in document.startViewTransition() and the browser cross-fades between the old and new state for free — no @keyframes required.

Basics

Detailed Explanation

The Default Effect: Cross-Fade

When you call document.startViewTransition(callback) and do not specify any custom animation, the browser performs a 300ms cross-fade between the captured before-and-after snapshots. This is the cheapest and most universal effect — it works on any kind of DOM change without requiring you to opt specific elements in via view-transition-name.

function update() {
  document.body.classList.toggle('dark');
}
if (document.startViewTransition) {
  document.startViewTransition(update);
} else {
  update();
}

Tweaking the timing

To override the default 300ms, target the two pseudo-elements that the browser auto-creates:

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 500ms;
  animation-timing-function: ease-in-out;
}

The root argument refers to the root snapshot group that the browser creates implicitly. Every element that does not have its own view-transition-name falls into this group, and the cross-fade happens at the document level.

Why this is better than opacity transitions

A naive transition: opacity 300ms only animates one element at a time and breaks down for layout-affecting changes (adding nodes, changing widths, swapping templates). The View Transitions API captures the entire visible viewport as raster snapshots, so even reflow-heavy mutations animate smoothly without thrashing the layout engine.

Use Case

Theme toggles, content swaps, search results re-rendering, or any state change where you want a polished cross-fade with zero per-element opt-in. Especially valuable for dynamic content where you do not know in advance which nodes will change.

Try ItView Transitions API Generator

Open full tool