Next.js 16.2のView Transitions — 共有要素トランジションでページ遷移が滑らかに
Next.js 16.2でView Transitions APIのサポートが強化されました(2026年3月18日 Next.js Blog)。<Link>コンポーネントにtransitionTypesプロパティが追加され、ナビゲーション時のアニメーションをより細かく制御できるようになっています。
View Transitionsと聞くと「ページ全体がフェードする」イメージがあるかもしれませんが、この機能の本質は共有要素トランジションです。一覧ページのタイトルが詳細ページのタイトルへ滑らかに移動する、といったアニメーションをライブラリなし・ゼロバンドルコストで実現できます。
View Transitionsの経緯
Next.js 15.2で試験的に導入(2025年2月)
View Transitionsは、Next.js 15.2で初めてexperimentalフラグとして追加されました(2025年2月26日 Next.js Blog)。
We’ve added a feature flag to enable the new experimental View Transitions API in React. This new API allows you to animate between different views and components in your application.
この時点ではReactのView Transition PRをベースにした初期実装で、ドキュメントも最小限でした。
Next.js 16.2で機能強化(2026年3月)
16.2では<Link>にtransitionTypesプロパティが追加され、ナビゲーションの方向やコンテキストに応じて異なるアニメーションを適用できるようになりました。
<Link href="/about" transitionTypes={['slide']}>About</Link>
View Transitions APIとは
View Transitions APIは、DOM更新の前後でブラウザが旧UIのスナップショットを撮影し、新UIとの間でCSSアニメーションを実行する仕組みです。
流れは以下の通りです。
- ブラウザが現在のUIのスナップショット(
::view-transition-old擬似要素)を撮る - DOMが更新される(新しいページのレンダリング)
- 旧スナップショット → 新UI(
::view-transition-new擬似要素)へCSSアニメーションで切り替え
単なるフェードインアウトではなく、同じnameを持つ要素同士の位置・サイズをブラウザが自動で補間してくれるのがポイントです。これが共有要素トランジションです。
ブラウザ対応状況
View Transitions API(同一ドキュメント内)の対応状況は以下の通りです(Can I Use)。

| ブラウザ | 対応状況 |
|---|---|
| Chrome | 111+ で対応 |
| Edge | 111+ で対応 |
| Safari | 18+ で対応(同一ドキュメント内のみ) |
| Firefox | 未対応(Nightlyでフラグ付きで利用可能) |
2025年10月にBaseline「Newly available」になったとのことで、Chrome/Edge/Safariの最新版では利用可能です。非対応ブラウザではアニメーションなしの通常遷移にフォールバックし、エラーにはなりません。
共有要素トランジションの仕組み
Vercelが公開している公式デモのソースコード(GitHub)を読むと、View Transitionsの本質がよくわかります。
<ViewTransition>コンポーネントで要素を紐づける
Reactの<ViewTransition>コンポーネント(React Documentation)で要素をラップし、nameプロパティで一意の識別子を指定します。
// 一覧ページ
<ViewTransition name={`post-title-${post.slug}`}>
<h2>{post.title}</h2>
</ViewTransition>
// 詳細ページ
<ViewTransition name={`post-title-${slug}`}>
<h1>{post.title}</h1>
</ViewTransition>
遷移前後で同じnameを持つ要素が存在すると、ブラウザが自動で位置・サイズの補間アニメーションを実行します。一覧ページの小さなタイトルが、詳細ページの大きなタイトルの位置へ滑らかに移動します。
アニメーションの制御
<ViewTransition>は複数のPropsでアニメーションを制御できます。
| Prop | 説明 |
|---|---|
name | 共有要素トランジションの識別子 |
enter | 要素が新規挿入される時のアニメーション |
exit | 要素が削除される時のアニメーション |
update | DOM内で変更が発生した時のアニメーション |
値は"auto"(ブラウザデフォルト)、"none"(無効)、またはCSSクラス名を指定します。
// 本文コンテンツは遷移アニメーションを無効化
<ViewTransition enter="auto" update="none">
<div>{post.body}</div>
</ViewTransition>
公式デモでも、共有要素以外の部分はupdate="none"で不要なアニメーションを抑制していました。何でもアニメーションさせるのではなく、動かすべき要素だけを選択的にアニメーションするのが効果的な使い方です。
実際に試してみた
ブログの一覧→詳細ページの遷移で共有要素トランジションを試してみました。
- Node.js: v20.19.5
- Next.js: 16.2.1
- ブラウザ: Chrome
デモの動作
実際の動作はこちらです。タイトルとタグが一覧から詳細ページへ滑らかに移動しています。
StackBlitzでも試せます: Open in StackBlitz
セットアップ
mkdir view-transitions-demo && cd view-transitions-demo
npm init -y
npm install next@latest react@latest react-dom@latest
next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
experimental: {
viewTransition: true,
},
};
export default nextConfig;
一覧ページ(src/app/page.tsx)
import Link from 'next/link';
import { ViewTransition } from 'react';
const posts = [
{ slug: 'nextjs-16', title: 'Next.js 16 がリリース', date: '2026-02-24', tag: 'Next.js', color: '#818cf8' },
{ slug: 'typescript-7', title: 'TypeScript 7.0 の新機能まとめ', date: '2026-02-10', tag: 'TypeScript', color: '#3178c6' },
{ slug: 'react-19', title: 'React 19 と Server Components', date: '2026-01-15', tag: 'React', color: '#58c4dc' },
];
export default function Home() {
return (
<div>
<h1>Posts</h1>
{posts.map((post) => (
<Link key={post.slug} href={`/post/${post.slug}`}>
<span>{post.date}</span>
<ViewTransition name={`post-tag-${post.slug}`}>
<span style={{ color: post.color }}>{post.tag}</span>
</ViewTransition>
<ViewTransition name={`post-title-${post.slug}`}>
<h2>{post.title}</h2>
</ViewTransition>
</Link>
))}
</div>
);
}
詳細ページ(src/app/post/[slug]/page.tsx)
import Link from 'next/link';
import { ViewTransition } from 'react';
export default async function PostPage({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = posts[slug];
return (
<div>
<Link href="/">← Back to posts</Link>
<ViewTransition name={`post-tag-${slug}`}>
<span style={{ color: post.color }}>{post.tag}</span>
</ViewTransition>
<ViewTransition name={`post-title-${slug}`}>
<h1>{post.title}</h1>
</ViewTransition>
{/* 本文は共有要素トランジションの対象外 */}
<ViewTransition enter="auto" update="none">
<div>{post.body}</div>
</ViewTransition>
</div>
);
}
ポイントは3つです。
- 一覧と詳細で同じ
name(post-title-${slug}、post-tag-${slug})を使う <ViewTransition>で囲む要素にはdisplay: inline-blockを指定する(Safari対応)- 本文など共有しない要素は
update="none"で不要なアニメーションを抑制する
注意: <ViewTransition>の配置
<ViewTransition>はDOM要素の**外側(親側)**に配置する必要があります。内側に入れるとアニメーションが発火しません。
// NG — アニメーションが発火しない
<div>
<ViewTransition name="title">
<h1>Title</h1>
</ViewTransition>
</div>
// OK
<ViewTransition name="title">
<div>
<h1>Title</h1>
</div>
</ViewTransition>
これまでのアプローチとの比較
| View Transitions API | Framer Motion | CSS Transition + State | |
|---|---|---|---|
| バンドルサイズ | 0KB(ブラウザネイティブ) | ~30KB | 0KB |
| Server Components対応 | 対応(Reactが統合) | Client Componentのみ | Client Componentのみ |
| 共有要素トランジション | ブラウザネイティブ | layoutId | 自前実装が必要 |
| ブラウザ対応 | Chrome/Edge/Safari | 全ブラウザ | 全ブラウザ |
| 学習コスト | CSS擬似要素の知識が必要 | Framer Motion API | 低い |
最大の利点はバンドルサイズゼロでServer Componentsと相性が良い点です。Framer Motionを使うためにClient Componentに変換する必要がなくなります。
一方、Firefoxが未対応のため、全ブラウザで一貫したアニメーションが必要な場合はまだFramer Motionの方が安全です。
prefers-reduced-motion への対応
Reactはprefers-reduced-motionメディアクエリを自動処理しないため、CSSで明示的に対応する必要があります。
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*) {
animation-duration: 0ms !important;
}
}
まとめ
View Transitionsの本質は共有要素トランジションです。ページ全体をフェードさせるのではなく、一覧のタイトルが詳細ページのタイトルへ滑らかに移動する、というようなアニメーションを<ViewTransition name={...}>で要素を紐づけるだけで実現できます。
Next.js 15.2(2025年2月)でexperimentalとして初めて導入され、16.2(2026年3月)でtransitionTypesの追加など機能強化が進んでいます。現時点ではまだexperimentalですが、Firefoxを除く主要ブラウザでは動作するため、プログレッシブエンハンスメントとして導入するのは十分ありだと思います。
自分が実際に動かしてみて一番印象的だったのは、<ViewTransition name={...}>で囲むだけで共有要素のアニメーションが動いた瞬間です。Framer MotionのlayoutIdに近い体験がゼロバンドルコストで得られるのは大きいと感じています。