Next.js view transitions work by wrapping the content that changes between two routes in React's ViewTransition component, so the browser animates between the old and new version instead of swapping them instantly on navigation.
// app/blog/[slug]/page.tsx
import { ViewTransition } from "react";
export default function BlogPost({ title }: { title: string }) {
return (
<ViewTransition name="post-title">
<h1>{title}</h1>
</ViewTransition>
);
}Navigate from a list of posts to this page, and if the list also wraps its own title in a ViewTransition with the same name, the browser animates the title smoothly from its position in the list to its position on the post page instead of just replacing it outright.
Why no install step is needed
The App Router already runs on a React version that includes ViewTransition, so importing it directly from react works without adding a separate package or an experimental flag to the project's configuration. The component itself is still considered part of React's newer feature set, so treat it as evolving rather than as settled API surface, even though it works today with no setup and no separate opt-in step for a project already running on the App Router.
What actually needs to match
Both the outgoing and incoming element need the same name value for the browser to treat them as one continuous element to animate between. Without a matching name on both sides, the content just changes the normal way, with no animation at all, since the browser has nothing to connect the two elements across the navigation.
| Situation | Result |
|---|---|
| Same name on both routes | Browser animates between the two elements |
| Name only on one side | No animation, content just changes |
| Browser lacks View Transitions API support | No animation, navigation still works |
Different animations for different navigations
Pass transitionTypes to a Link to tell a ViewTransition which kind of navigation just happened, such as moving forward through a list versus going back.
// app/nav.tsx
import Link from "next/link";
export default function PostLink({ slug }: { slug: string }) {
return <Link href={`/blog/${slug}`} transitionTypes={["nav-forward"]}>Read post</Link>;
}A view transition further down the tree can check for "nav-forward" and apply a different animation than it would for a back navigation, without the link itself needing any extra logic beyond this one prop. This is what lets a list-to-detail navigation feel different from a detail-to-list return, using the same underlying component on both routes.
For how a click reaches the new route before any animation runs, see Client-Side Navigation in Next.js: What Happens on a Link Click. For the rest of the props a link accepts alongside transitionTypes, read The Next.js Link Component: Props and Behavior Explained.
Rune AI
Key Insights
- Import ViewTransition directly from react, no extra package or config needed.
- Give matching elements on both routes the same name so the browser can animate between them.
- Browsers without View Transitions API support still navigate correctly, just without the animation.
- The transitionTypes prop on Link lets a ViewTransition apply a different animation per navigation.
- This feature works independently of whether Cache Components is enabled.
Frequently Asked Questions
Do I need to install anything to use ViewTransition?
What happens in a browser that does not support the View Transitions API?
Do I need Cache Components enabled for this to work?
Conclusion
Wrapping changing content in React's ViewTransition component animates it across a Next.js navigation with no extra configuration. The animation only runs in browsers that support the View Transitions API, and navigation itself always works correctly even where it does not.
More in this topic
`generateMetadata` Explained with Real Examples
What generateMetadata does, when it runs, and how to use it for real routes: awaited params, deduplicated data fetching, extending parent metadata, and returning a 404 from metadata.
Canonical URLs in Next.js: `metadataBase`, `alternates.canonical`, and Dynamic Pages
How canonical URLs work in the Next.js App Router: setting metadataBase once, writing alternates.canonical per route, handling dynamic segments, and what happens when the base URL is missing.
Open Graph and Twitter Card Metadata in Next.js
How to write Open Graph and Twitter card metadata in the Next.js App Router: the openGraph and twitter fields, automatic card defaults, article tags, and image merge rules.