View Transitions API実践:クロスページ/クロスドキュメントアニメーション遷移
ページ遷移の進化
| 手法 | 適用範囲 | 実装複雑度 | ブラウザネイティブ | パフォーマンス |
|---|---|---|---|---|
| CSS transition | 単一コンポーネント | 低 | ✅ | 高 |
| Framer Motion / GSAP | SPAルーティング | 高 | ❌ | 中 |
| Shared Element Transition | SPA + MPA | 低 | ✅ | 高 |
| View Transitions API | SPA + MPA | 低 | ✅ | 高 |
View Transitions APIはブラウザが旧→新状態のスナップショット、アニメーション、クリーンアップを自動処理。開発者は「いつ遷移するか」「どうアニメーションするか」だけを宣言します。
SPAでのView Transitions
基本的な使い方:document.startViewTransition
function navigateTo(newRoute: string) {
if (!document.startViewTransition) {
updateDOM(newRoute);
return;
}
document.startViewTransition(() => {
updateDOM(newRoute);
});
}
ブラウザが自動実行:
- 旧状態のスナップショットを取得(
::view-transition-old) - コールバックを実行し、DOMを更新
- 新状態のスナップショットを取得(
::view-transition-new) - 2つのスナップショット間でクロスフェードアニメーション
カスタム遷移アニメーション
デフォルトのクロスフェード
::view-transition-old(root) {
animation: 0.3s ease-in both fade-out;
}
::view-transition-new(root) {
animation: 0.3s ease-out both fade-in;
}
スライド切り替え効果
::view-transition-old(root) {
animation: 0.4s ease-in both slide-to-left;
}
::view-transition-new(root) {
animation: 0.4s ease-out both slide-from-right;
}
@keyframes slide-to-left {
to { transform: translateX(-100%); }
}
@keyframes slide-from-right {
from { transform: translateX(100%); }
}
共有要素遷移:クロスコンポーネントアニメーション
要素にview-transition-nameを設定すると、ブラウザが旧→新位置間でFLIPアニメーションを自動実行:
.card-image {
view-transition-name: card-img;
}
.card-title {
view-transition-name: card-title;
}
実践:リスト→詳細ページのHeroアニメーション
function openDetail(cardId: string) {
document.startViewTransition(() => {
document.querySelector('.list-page')!.style.display = 'none';
document.querySelector('.detail-page')!.style.display = 'block';
document.querySelector(`#card-${cardId} img`)!
.style.viewTransitionName = 'hero-image';
document.querySelector('.detail-hero img')!
.style.viewTransitionName = 'hero-image';
});
}
リストカード画像 → 詳細ページ大画像間でスムーズなスケール+位置アニメーションが自動実行。
MPAクロスドキュメント遷移
Chrome 111+はクロスドキュメント(クロスページナビゲーション)のView Transitionsをサポート:
クロスドキュメント遷移の有効化
<meta name="view-transition" content="same-origin">
1行のmetaタグで、同一オリジンナビゲーションに自動クロスフェード!
ナビゲーション方向によるカスタムCSS
@media (navigation: forward) {
::view-transition-old(root) { animation: slide-to-left; }
::view-transition-new(root) { animation: slide-from-right; }
}
@media (navigation: back) {
::view-transition-old(root) { animation: slide-to-right; }
::view-transition-new(root) { animation: slide-from-left; }
}
高度なテクニック
アニメーション不要な要素の除外
header, footer {
view-transition-name: none;
}
動的view-transition-name設定
document.querySelectorAll('.card').forEach((card, i) => {
card.style.viewTransitionName = `card-${i}`;
});
画像ロード待ち後に遷移
document.startViewTransition(async () => {
updateDOM(newRoute);
await document.querySelector('.detail-hero img')?.decode();
});
ToolsKuとの統合
- CSSアニメーションツール:View Transitions用の@keyframesを生成
- グラデーションジェネレーター:遷移オーバーレイのグラデーション背景を作成
- 画像コラージュ:コラージュレイアウト切替時に共有要素遷移を使用
パフォーマンス考慮事項
| 側面 | 推奨 |
|---|---|
| スナップショットサイズ | 大きな要素にview-transition-nameを設定しない |
| 遷移時間 | 200-400msが知覚的に最適な範囲 |
| 同時遷移 | 複数の共有要素が同時アニメーションするとGPU負荷が増加 |
| レイアウトスラッシング | コールバック内でレイアウト再計算をトリガーしない(スナップショットが不正確になる) |
よくある質問
startViewTransitionコールバック内で非同期DOM更新可能か?
可能です。コールバックはasync関数をサポートし、ブラウザはPromise解決後に新スナップショットを取得します。ただし待機中は旧スナップショットが表示され続け、長すぎる待機はカクつき感の原因になります。
クロスドキュメント遷移とSPA遷移の違い?
SPAはdocument.startViewTransition()で手動トリガー、MPAは<meta name="view-transition">で自動トリガー。両者は同じCSS擬似要素とアニメーション定義体系を共有します。
View Transitionsのデバッグ方法?
Chrome DevTools → Elementsパネルで::view-transition-group等の擬似要素ツリーを確認。Animationパネルでフレーム単位の遷移アニメーションデバッグが可能。
まとめ
View Transitions APIはページ遷移を手動FLIP計算からブラウザネイティブのスナップショット+アニメーションに変換し、実装複雑度を大幅に削減します。SPAはdocument.startViewTransition()、MPAはmetaタグ、共有要素はview-transition-name—3つのシナリオが1つのCSS擬似要素体系に統一される、モダンWebアプリのページ遷移の最適解です。
ブラウザローカルツールを無料で試す →