View Transitions API
Overview
The View Transitions API provides a native mechanism for creating animated transitions between different views (DOM states) in a web application. It works for both SPAs (same-document) and MPAs (cross-document), eliminating the need for JavaScript animation libraries for page transitions.
When to Use
- Page-to-page transitions in Next.js, Nuxt, or any framework
- Animating between UI states (list ↔ detail, tabs, modal open/close)
- Creating smooth "shared element" transitions (image expanding to detail page)
- Replacing Barba.js or custom page transition code with native APIs
Same-Document Transitions (SPA)
// Basic transition
document.startViewTransition(() => {
// Update the DOM
updateContent(newContent);
});
// With async operations
document.startViewTransition(async () => {
const data = await fetchNewPage(url);
document.querySelector('#content').innerHTML = data;
});
CSS for Transitions
/* Default crossfade (works automatically) */
::view-transition-old(root) {
animation: fade-out 0.3s ease-out;
}
::view-transition-new(root) {
animation: fade-in 0.3s ease-in;
}
/* Named transitions for specific elements */
.hero-image {
view-transition-name: hero;
}
::view-transition-old(hero) {
animation: scale-down 0.4s ease-in-out;
}
::view-transition-new(hero) {
animation: scale-up 0.4s ease-in-out;
}
Cross-Document Transitions (MPA)
/* Enable in CSS — no JavaScript needed */
@view-transition {
navigation: auto;
}
/* Shared elements across pages */
.product-card img {
view-transition-name: product-image;
}
.product-detail img {
view-transition-name: product-image;
}
Next.js Integration
// app/layout.tsx
import { unstable_ViewTransition as ViewTransition } from 'react'
export default function Layout({ children }) {
return (
<html>
<body>
<ViewTransition>{children}</ViewTransition>
</body>
</html>
)
}
Guidelines
- Use
view-transition-nameto create shared element transitions - Each
view-transition-namemust be unique on the page at transition time - Respect
prefers-reduced-motion— disable animations for accessibility - Use CSS for transition styling, JavaScript for triggering
- Progressive enhancement — transitions are purely visual, pages work without them
Anti-Patterns
- ❌ Using duplicate
view-transition-namevalues on the same page - ❌ Ignoring
prefers-reduced-motionmedia query - ❌ Heavy JavaScript animations when CSS view transitions suffice
- ❌ Not providing fallback for unsupported browsers