モバイルアプリを操作しているとき、一覧画面のサムネイル画像をタップすると、その画像が拡大しながらスルスルと詳細画面のメインビジュアルへと吸い込まれるように遷移する――。
このような連続性のあるリッチな画面遷移(トランジション)は、ユーザーに現在位置を直感的に伝え、待ち時間のストレスを大幅に軽減するUI/UXとして非常に効果的です。
しかし、従来のWeb開発においてこの表現を実現しようとすると、SPA(Single Page Application)の複雑なルーティングライブラリを組み込み、旧DOMと新DOMを同時に描画して位置と大きさをJavaScriptで計算・アニメーションさせ、終わったら旧DOMを削除するという、極めて重労働で壊れやすい実装が必要でした。ましてや、通常のマルチページサイト(MPA)ではほぼ不可能な領域でした。
その常識を根底から覆したのが、Web標準仕様である「View Transitions API」です。
ブラウザが新旧画面のスナップショット(スクリーンショット)を自動的にキャプチャし、その差分をCSSアニメーションで滑らかに繋いでくれるため、わずか数行の記述でネイティブアプリ並みのトランジションが実現します。さらに現在では、SPAだけでなく通常のHTMLページ遷移(MPA / Cross-document)にも対応し、実務での採用が一気に加速しています。
本記事では、View Transitions APIの基本的な仕組みから、SPAでの使い方(`document.startViewTransition`)、MPAでの完全CSS実装(`@view-transition`)、ヒーローアニメーションの実装例、そしてアクセシビリティの必須対策まで、徹底解説します!
1. View Transitions APIとは?なぜこれほど革命的なのか
View Transitions APIは、「DOMの変更前」と「DOMの変更後」の見た目をブラウザが自動的に画像スナップショットとして記録し、その間をCSSアニメーションで滑らかに補間してくれる仕組みです。
| 比較項目 | 従来の画面遷移アニメーション | View Transitions API |
|---|---|---|
| DOM構造 | 新旧のDOM要素を画面上に同時に共存させる必要があった | DOMを普通に切り替えるだけでOK(ブラウザが擬似要素で処理) |
| 位置・サイズの計算 | getBoundingClientRect() 等で座標を計算してFLIPアニメーションを自作 |
ブラウザが座標と拡大縮小を自動計算(差分を自動補間) |
| 実装の難易度 | 非常に高く、DOMの二重管理でバグやアクセシビリティ低下の温床に | JavaScript数行、またはCSS 1行で完結 |
| MPA(通常のWebページ)対応 | ページ再読み込み(白画面フラッシュ)が入るため不可能だった | 同一オリジン間のリンク遷移ならCSSのみで動作可能 |
開発者が複雑なアニメーション制御コードを書かなくても、ブラウザ自身が最前面に専用の擬似要素ツリー(スナップショットレイヤー)を一時的に生成し、古い見た目をフェードアウト、新しい見た目をフェードインさせてくれます。
2. 内部の仕組み:ブラウザの裏側で何が起きているのか?
View Transitions APIが動作する際、ブラウザの最上位レイヤーに以下のような特殊な擬似要素ツリーが生成されます。
::view-transition
└─ ::view-transition-group(root)
└─ ::view-transition-image-pair(root)
├─ ::view-transition-old(root) ← 切り替え前のスナップショット
└─ ::view-transition-new(root) ← 切り替え後のスナップショット
- キャプチャ開始:APIが呼び出されると、ブラウザは現在の画面状態を「静止画(
::view-transition-old)」として撮影します。 - DOMの更新:画面の描画を一時的に停止(フリーズ)させた状態で、開発者が指定したDOM変更(ページの書き換え)を実行します。
- 新しい状態のキャプチャ:更新後のDOMを描画し、新しい画面を「静止画(
::view-transition-new)」として撮影します。 - トランジションアニメーション:デフォルトでは、古い画面がフェードアウト(opacity: 1 → 0)し、同時に新しい画面がフェードイン(opacity: 0 → 1)するクロスフェードが自動実行されます。
- レイヤーの破棄:アニメーションが完了すると、擬似要素ツリーは自動的に消去され、通常のインタラクティブなページに戻ります。
3. 【SPA編】JavaScriptを使った基本的な実装方法
まずは、React、Vue、あるいはVanilla JSで画面の一部やタブを切り替える「同一ドキュメント内(Same-document)」の実装から見ていきましょう。
基本の書き方:document.startViewTransition()
使い方は極めてシンプルです。DOMを更新する処理(関数の実行)を document.startViewTransition() のコールバック関数の中に渡すだけです。
// 未対応ブラウザへのフォールバック(プログレッシブエンハンスメント)
function updateContent(newHtml) {
const container = document.querySelector('#main-content');
// View Transitions APIがサポートされていない場合は通常通り更新
if (!document.startViewTransition) {
container.innerHTML = newHtml;
return;
}
// APIを呼び出してDOMを更新
document.startViewTransition(() => {
container.innerHTML = newHtml;
});
}
たったこれだけで、container.innerHTML が書き換わる瞬間に、画面全体がふわっと滑らかにクロスフェードするようになります。
4. 【MPA編】CSSだけで動く!複数ページ間のトランジション
静的サイト(AstroやWordPress、通常のHTML/PHPサイトなど)で、ページ間をリンクで遷移する際にアニメーションさせたい場合は、なんとJavaScriptすら不要です。
CSSに @view-transition を1行書くだけ
遷移元と遷移先の両方のHTMLに読み込まれる共通CSSファイルに、以下のルールを記述します。
/* 同一オリジン間のリンク遷移でView Transitionを有効化 */
@view-transition {
navigation: auto;
}
これだけで、ユーザーがサイト内の <a href="..."> リンクをクリックして別ページへ移動した際、従来の「画面が一瞬真っ白になってから再描画される」という無骨な挙動が消え去り、シームレスなクロスフェード遷移に早変わりします。
5. 応用編:特定の要素同士を繋ぐ「ヒーローアニメーション」
画面全体のフェードだけでなく、「一覧ページの画像」が「詳細ページのメイン画像」へと滑らかに変形・移動する、いわゆる共有要素トランジション(Shared Element Transition)を作ってみましょう。
① view-transition-name で要素に一意の名前をつける
繋げたい要素に対して、CSSの view-transition-name プロパティで「同じ名前」を指定します。
<!-- 一覧ページ(list.html) -->
<div class="card">
<img src="item-01.jpg" class="card-thumb" alt="商品画像">
<h2>スニーカー A</h2>
</div>
<!-- 詳細ページ(detail.html) -->
<div class="detail-wrapper">
<img src="item-01.jpg" class="detail-hero" alt="商品画像">
<h1>スニーカー A</h1>
</div>
/* CSS */
/* 一覧側のサムネイル画像 */
.card-thumb {
view-transition-name: product-hero-image;
}
/* 詳細側のメイン画像 */
.detail-hero {
view-transition-name: product-hero-image;
}
【何が起きるのか?】
ブラウザは view-transition-name: product-hero-image; という同一の名前を見つけると、全体フェードの対象からその要素だけを独立させます。
そして、「一覧画面での位置・サイズ」から「詳細画面での位置・サイズ」へと、要素を自動的にスーッと拡大・移動(モーフィング)させてくれます。
※注意:同一ページ内に同じ view-transition-name を持った要素が複数同時に存在するとエラーになり、トランジションがスキップされます。一覧ページに複数のカードが並ぶ場合は、クリック時にJavaScriptで動的にそのカードだけに名前を付与するか、ユニークなID名(例:product-item-123)を割り振るのが鉄則です。
6. アニメーションを自分好みにカスタマイズする
デフォルトのクロスフェードだけでなく、スライドインやイージングの調整もCSSで自由自在に上書きできます。
/* 画面全体のトランジション速度とイージングを調整 */
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.4s;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
/* 古い画面が左にスライドアウト */
@keyframes slide-out-left {
from { transform: translateX(0); }
to { transform: translateX(-100%); }
}
/* 新しい画面が右からスライドイン */
@keyframes slide-in-right {
from { transform: translateX(100%); }
to { transform: translateX(0); }
}
::view-transition-old(root) {
animation-name: slide-out-left;
}
::view-transition-new(root) {
animation-name: slide-in-right;
}
7. 実務導入で絶対に忘れてはならない注意点とアクセシビリティ
優れた演出であっても、ユーザーに悪影響を与えてはなりません。実務で公開する前に必ず以下の2点を確認してください。
① prefers-reduced-motion への配慮(必須)
めまいや光感受性発作、前庭覚機能障害を抱えるユーザーは、OSの設定で「視覚効果を減らす(アニメーションをオフにする)」を選択しています。この設定を尊重し、不要な揺れや移動を無効化するメディアクエリを必ず記述しましょう。
/* アニメーションを抑える設定のユーザーには即座に切り替える */
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
animation: none !important;
}
}
② プログレッシブエンハンスメントの徹底
Chromium系ブラウザ(Chrome, Edge)をはじめ主要ブラウザでの対応が進んでいますが、古いブラウザや環境によっては機能しない場合があります。
View Transitions APIは「動かなくてもWebサイトのコンテンツ閲覧や遷移自体は正常に行える」という特性を持っています。アニメーションが動かない環境でも壊れないよう、条件分岐(if (document.startViewTransition))を活用した設計を心がけてください。
8. まとめ:これからのWebデザインに不可欠な標準技術
View Transitions APIの登場により、これまでネイティブアプリの独壇場だった「触っていて気持ちいい画面遷移」が、Web標準のCSSとJavaScriptだけで誰でも手軽に作れる時代が到来しました。
- SPAの場合:
document.startViewTransition()でDOM変更を囲むだけ。 - MPAの場合:CSSに
@view-transition { navigation: auto; }を書くだけでページ遷移が滑らかに。 - 共有要素アニメーション:
view-transition-nameで新旧要素に同じ名前をつければ自動で拡大・移動。 - アクセシビリティ:
prefers-reduced-motionで動きを抑制できる安全設計を忘れない。
ユーザーの離脱を防ぎ、サイトのブランド体験を一段階引き上げるために、ぜひご自身のWebサイトやプロジェクトにView Transitions APIを取り入れてみてください!

