View Transitions API
画面切り替えの一瞬をJSアニメ実装なしで滑らかにできる。DOM前後の状態をスナップショットし擬似要素で自動補間する仕組みを、SPA/MPA両対応の内部動作から正確に解きます。
- 1.startViewTransition() は「旧DOMの見た目をキャプチャ→DOM更新→新DOMの見た目をキャプチャ→両者を擬似要素ツリーでクロスフェード/変形」という4段階のアルゴリズムで動く。
- 2.view-transition-name を振った要素は個別の擬似要素ペア(::view-transition-old/new)に分離され、位置・サイズの差分は自動でトランスフォーム補間される。同名重複はエラーで遷移が中断する。
- 3.クロスドキュメント(MPA)遷移は @view-transition ルールとNavigation APIの上に構築され、遷移元・遷移先の2文書にまたがる非同期プロセスとして進行する。
何を解決するAPIか
画面が切り替わる瞬間に要素をクロスフェードさせたり、カード画像を詳細ページの大画像へシームレスに変形させたりする表現は、従来はFLIP法(First-Last-Invert-Play)を手書きし、transformとopacityをアニメーションさせるJSを大量に書く必要がありました。View Transitions APIは、この「旧状態のスナップショット取得」「DOM更新」「新状態のスナップショット取得」「両者の差分補間」という一連の手順をブラウザ内部のアルゴリズムとして標準化したものです。SPA内のDOM更新(同一ドキュメント遷移)と、通常のページ間ナビゲーション(クロスドキュメント遷移)の両方をカバーします。
同一ドキュメント遷移の内部アルゴリズム
document.startViewTransition(callback) を呼ぶと、ブラウザは以下の順序でステップを踏みます。
- キャプチャ(旧状態):
view-transition-nameが指定された要素それぞれについて、現在のレンダリング結果(ラスタ画像)とボックスのジオメトリ(位置・サイズ・writing-mode等)を記録する。 - DOM更新: 渡した
callbackを同期的に実行する。ここでDOM操作・クラス切り替えを行う(非同期処理を含む場合はPromiseを返すとその完了を待つ)。 - キャプチャ(新状態): 更新後のレイアウトを確定させ、同じ
view-transition-nameを持つ要素の新しいジオメトリを取得する。 - 擬似要素ツリーの構築とアニメーション開始: 新旧のキャプチャから
::view-transition以下の擬似要素ツリーを生成し、CSSアニメーションとして再生する。
コールバック内のDOM更新は同期的またはPromiseとして扱われ、完了を待ってから新状態のキャプチャに進みます。非同期のデータ取得を先に済ませ、コールバックには「見た目を変えるDOM操作」だけを渡すのが定石です。コールバックが reject すると遷移全体がスキップされ、DOMは更新されたまま古い見た目のアニメーションは行われません。
擬似要素ツリー:スナップショットの実体
startViewTransition() が生成する擬似要素は、documentのルートに次のような入れ子構造で挿入されます。
::view-transition
└─ ::view-transition-group(name)
└─ ::view-transition-image-pair(name)
├─ ::view-transition-old(name)
└─ ::view-transition-new(name)
view-transition-name を指定していない要素は、既定で root という単一グループにまとめられ、ページ全体がひとつの静止画としてクロスフェードします。個別に動かしたい要素(見出し・カード画像など)にだけ固有の名前を振ると、その要素専用のグループが分離され、他要素と独立して補間されます。
.hero-image {
view-transition-name: hero;
}
::view-transition-group は新旧ジオメトリの差(位置・サイズ・回転相当の変形)をtransformとwidth/heightの補間として自動生成し、::view-transition-image-pairの内側で ::view-transition-old と ::view-transition-new が既定で相互にクロスフェード(opacityのアニメーション)します。これはすべて実CSSのアニメーションとして走るため、開発者は通常のanimationプロパティで上書き・カスタマイズできます。
同時に有効な view-transition-name が複数の要素で重複すると、その遷移はエラーとして中断されます(DOM更新自体は行われるが、アニメーションはスキップ)。リスト内の要素に動的な名前(item-${id}のように)を振り、遷移完了時か遷移前に確実にリセットする実装が必須です。
レイアウト差分の自動補間の正体
「自動補間される」とは具体的には、新旧2つのキャプチャ画像のボックスサイズ・位置が異なる場合、ブラウザが ::view-transition-group に対して開始時ジオメトリから終了時ジオメトリへの transform(平行移動・拡大縮小)アニメーションを生成することを指します。画像そのものをピクセル単位で再合成しているのではなく、各時点のスナップショットを1枚の合成レイヤーとして扱い、それをアフィン変換で動かしている点が重要です。これにより文字の再レイアウトやリフローを伴わない、コンポジタスレッド寄りの安価なアニメーションになります。
CSSでの制御
擬似要素は通常のCSSセレクタで狙えるため、既定のクロスフェードを上書きできます。
::view-transition-old(hero),
::view-transition-new(hero) {
animation-duration: 0.4s;
mix-blend-mode: normal; /* 既定のブレンドを外して二重描画のにじみを防ぐ */
}
/* 特定名だけ動きを変える */
::view-transition-group(hero) {
animation-timing-function: cubic-bezier(0.2, 0, 0, 1);
}
@media (prefers-reduced-motion: reduce) と組み合わせて ::view-transition-group(*) { animation: none !important; } のように無効化するのが、アクセシビリティ上の定石です。遷移全体をJSから中断したい場合は、startViewTransition()が返す ViewTransition オブジェクトの skipTransition() を呼びます。
| 段階を表すPromise | 解決タイミング |
|---|---|
| updateCallbackDone | コールバックのDOM更新が完了した時点 |
| ready | 擬似要素ツリー生成が終わりアニメーション開始直前 |
| finished | アニメーションが完了し擬似要素が破棄された時点 |
SPAとMPA(クロスドキュメント)両対応
同一ドキュメント内のstartViewTransition()に加え、クロスドキュメント遷移として通常のページ遷移(別URLへのフルナビゲーション、いわゆるMPA構成)にも同じ仕組みが適用されます。有効化はJS呼び出しではなくCSSの宣言で行います。
/* 遷移元・遷移先の両方のドキュメントに書く必要がある */
@view-transition {
navigation: auto;
}
navigation: auto を持つ文書間の同一オリジンナビゲーションで、ブラウザは遷移元ページの見た目をキャプチャした直後にアンロードし、新ドキュメントのレンダリング完了後に新状態をキャプチャして同じ擬似要素アルゴリズムを適用します。同一ドキュメント版との違いは、DOM更新のステップが「JSコールバック」ではなく「文書のナビゲーションそのもの」に置き換わる点だけで、擬似要素ツリー・補間・CSS制御の仕組みは共通です。view-transition-name を新旧ページで同じ値にした要素同士(例:一覧の画像と詳細ページの画像)は自動でペアリングされ、変形アニメーションの対象になります。
navigation: auto は遷移元・遷移先双方の文書に必要です。片方にしか無いと発火しません。また別オリジンへの遷移、target="_blank"等で別タブ・別ウィンドウが開くナビゲーション、ブラウザのbfcache復元によるナビゲーションでは適用対象外です。ナビゲーションの中断(別リンクへの割り込み等)が起きると進行中の遷移はskipTransition()相当で打ち切られます。
まとめ
View Transitions APIは「旧状態をキャプチャ→DOM/ドキュメント更新→新状態をキャプチャ→擬似要素ツリーで差分をtransform・opacityアニメーションとして再生」という4段階アルゴリズムに要約できます。view-transition-nameで要素ごとにグループを分離すると、それぞれ独立した::view-transition-old/::view-transition-newペアとして補間対象になり、名前の重複はエラーで遷移全体を止めます。同一ドキュメント遷移はstartViewTransition()、クロスドキュメント遷移は双方の文書への@view-transition { navigation: auto }宣言で有効化され、内部の擬似要素・補間ロジックは共通です。差分の補間はピクセル再合成ではなくスナップショットのアフィン変換なので、合成レイヤー寄りの軽い処理に収まります。実装ではprefers-reduced-motionでの無効化と、Navigation APIを使う遷移制御との組み合わせによる体感速度の底上げを合わせて検討してください。
Web/フロントエンド Article
View Transitions APIを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
View Transitions
比較で見る軸
難易度: advanced / カテゴリ: Web/フロントエンド / タグ数: 6
導入後に効く点
view-transition-name を振った要素は個別の擬似要素ペア(::view-transition-old/new)に分離され、位置・サイズの差分は自動でトランスフォーム補間される。同名重複はエラーで遷移が中断する。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- Web/フロントエンド
- タグ数
- 6
判断チェックリスト
- 自社の用途が「View Transitions / CSS」に近いか確認する。
- 強みである「startViewTransition() は「旧DOMの見た目をキャプチャ→DOM更新→新DOMの見た目をキャプチャ→両者を擬似要素ツリーでクロスフェード/変形」という4段階のアルゴリズムで動く。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。