View Transitions

Route changes are a unique in-between state. Without visual continuity, content disappears then reappears abruptly—users lose spatial context. Where did that card go? Am I on a new page or the same page?

React's <ViewTransition> component wraps the browser's View Transitions API, enabling smooth animated transitions between routes with a declarative API.

Page-Level Transitions

Wrap page content in <ViewTransition> with enter/exit animations:

import { ViewTransition } from 'react'; export function SlideRightTransition({ children }) { return ( <ViewTransition enter="slide-from-right" exit="slide-to-right" default="none"> {children} </ViewTransition> ); } // In your page export default function DashboardPage() { return ( <SlideRightTransition> <div>...</div> </SlideRightTransition> ); }

Define the animations in CSS with @keyframes.

Shared Element Transitions

Connect elements across pages with the same name prop. When navigating, the element morphs from its position on one page to its position on the next:

// In the list view (Dashboard) <ViewTransition name={`post-card-${post.slug}`} share="morph"> <Card>{post.title}</Card> </ViewTransition> // In the detail view (Post page) <ViewTransition name={`post-card-${slug}`} share="morph"> <Card>{post.title}</Card> </ViewTransition>

The card animates smoothly from the list to its position on the detail page. Users see visual continuity—the same element moving, not disappearing and reappearing.

Directional Navigation

Create a sense of spatial hierarchy with directional transitions:

// Going "into" a detail page - slide from right <SlideRightTransition> <PostDetail /> </SlideRightTransition> // Going "back" to a list - slide from left <SlideLeftTransition> <PostList /> </SlideLeftTransition>

Forward navigation slides right; back navigation slides left. Users build a mental model of your app's structure.

Browser Support

View Transitions use the native View Transitions API. In unsupported browsers, navigation works normally without animation—progressive enhancement by default.

October 21, 2025Updated February 13, 2026274 words