back to blog
developmentDecember 29, 2025 · 3 min read

The View Transitions API: Smooth Page Animations Without a Framework

The View Transitions API lets you animate between page states with just a few lines of CSS and JavaScript. Here's how it works and where it shines.

Dan Holloran
Dan Holloran
Senior Frontend & Fullstack Developer
The View Transitions API: Smooth Page Animations Without a Framework image

One of the things native mobile apps have always had over the web is smooth transitions between screens. Navigating in a browser traditionally means an instant swap — old content gone, new content appears. The View Transitions API changes this with a browser-native mechanism for animating between states, and it's now in all major browsers.

How It Works

The API works by capturing a screenshot of the current state, applying the new state, then cross-fading between the two using CSS animations you control. The core is a single method:

js
document.startViewTransition(() => {
  // Any DOM mutation here will be animated
  updatePageContent();
});

Without any extra CSS, you get a smooth cross-fade for free. That alone is a significant upgrade for most SPAs. But the real power comes when you name elements to create matched transitions.

Named Elements and Matched Transitions

When you give an element a view-transition-name, the browser tracks that element across the transition and animates it from its old position and size to its new one:

css
/* Mark the element you want to animate across views */
.hero-image {
  view-transition-name: hero-image;
}

.product-thumbnail {
  view-transition-name: product-thumb;
}
js
document.startViewTransition(() => {
  // Swap the list view for the detail view
  container.innerHTML = renderDetailView(product);
});

If both views have an element with view-transition-name: hero-image, the browser morphs the element between its two positions — like a shared element transition in native apps. The animation is driven by CSS, so you have full control:

css
/* Target the animated snapshot pairs */
::view-transition-old(hero-image) {
  animation: fade-out 0.3s ease;
}

::view-transition-new(hero-image) {
  animation: fade-in 0.3s ease;
}

/* Or let the browser interpolate position/size automatically */
::view-transition-group(hero-image) {
  animation-duration: 0.4s;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

Multi-Page Applications with Navigation API

The initial release of View Transitions only covered same-document transitions. Cross-document (MPA) support has now landed in Chrome and is coming to other browsers. You opt in with a single meta tag:

html
<meta name="view-transition" content="same-origin" />

With this in place, navigating between pages on the same origin automatically triggers a cross-fade. Add view-transition-name to persistent elements (nav, header, a hero image that exists on multiple pages) and you get native-feeling page transitions with zero JavaScript.

Practical Tips

A few patterns that make the API easier to work with in real projects:

js
// Graceful degradation — not all browsers support this yet
if (!document.startViewTransition) {
  updatePageContent();
  return;
}

const transition = document.startViewTransition(() => {
  updatePageContent();
});

// Wait for the animation to finish before doing cleanup
await transition.finished;
cleanup();

Keep view-transition-name values unique per page — duplicate names cause the browser to skip the matched animation for those elements. For list items, you can set the name dynamically:

js
items.forEach((item) => {
  item.element.style.viewTransitionName = `item-${item.id}`;
});

View Transitions won't replace dedicated animation libraries for complex choreography, but for the common case of animating between routes and promoting individual elements across page changes, it's the right tool — fast, native, and CSS-controllable.