書き方
Same-document(SPA向け)の基本
JavaScriptでDOM操作をしているページで試せる、もっとも基本的な使い方です。
実装はとてもシンプルで、DOM更新処理を document.startViewTransition() の引数として渡すだけです。
CSS
.panel {
display: none;
}
.panel.is-open {
display: block;
}
// View Transition APIを使う書き方
function showDetail() {
document.startViewTransition(() => {
// 遷移後のDOMの変更を記述
document.querySelector('.panel').classList.add('is-open');
});
}
これだけでデフォルトのクロスフェードアニメーションが付きます。驚くほどシンプルですよね。
プログレッシブエンハンスメントとして書く
もし非対応ブラウザも考慮するなら、サポートチェックを1行加えるだけで安全に動きます。
JS
function updateUI(callback) {
if (!document.startViewTransition) {
callback(); // 非対応ブラウザは従来通り
return;
}
document.startViewTransition(callback);
}
function showDetail(){
// 遷移後のDOMの変更を記述
document.querySelector('.panel').classList.add('is-open');
}
updateUI(showDetail); //ボタンクリックなどにバインド
CSSでアニメーションをカスタマイズする
デフォルトのクロスフェードをカスタマイズしたい場合は、View Transition APIが提供する専用の擬似要素をCSSで記述します。
3-1からJSの記述変更は必要ありません!
CSS
/* 遷移前の画面(古いスナップショット) */
::view-transition-old(root) {
animation: slide-out 0.3s ease-in;
}
/* 遷移後の画面(新しいスナップショット) */
::view-transition-new(root) {
animation: slide-in 0.3s ease-out;
}
@keyframes slide-out {
to {
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes slide-in {
from {
transform: translateX(100%);
opacity: 0;
}
}
::view-transition-old と ::view-transition-new が新旧スナップショットに対応しています。この2つをCSSアニメーションで制御するだけで、スライドやフェード、スケールなど自由な演出が作れます。
view-transition-name で要素を個別にアニメーションさせる
特定の要素に view-transition-name を指定すると、その要素だけを個別にアニメーションさせられます。サムネイルが詳細表示にぬるっと拡大するような、iOSアプリでよく見るアニメーションがこれで実現できます。
CSS
/* アニメーションさせたい要素に名前をつける */
.product-thumbnail {
view-transition-name: hero-image;
}
名前をつけた要素は、変化前後の位置・サイズの間をブラウザが自動で補間してくれます。これだけで、クリックした画像が詳細ページの大きな画像へとなめらかに変形する演出が完成します。
注意点:view-transition-name はページ内でユニークな値にする
同じ view-transition-name を複数の要素に付与すると正しく動作しません。リスト要素など動的に生成される要素の場合は、JavaScriptで一意の値を割り当てるか、2025年から使えるようになった view-transition-name: match-element を活用しましょう。
CSS
/* match-element:要素が自動でユニークな名前を持つ */
.list-item {
view-transition-name: match-element;
}
view-transition-name: match-element はブラウザが「変更前の要素」と「変更後の要素」を同じオブジェクト(同一の参照)として認識できる場合は利用できますが、変更後の要素が動的に生成されたりするケースでは単なるクロスフェードとなってしまうため、その場合は動的にview-transition-nameを変更前後の要素に付与する必要があります。この時、変更前後で同じview-transition-nameが付与された要素がどちらも表示状態だとview-transition-nameの競合エラーが起きてしまうため、変更の前後で同じview-transition-nameを持つ要素が重複して表示されないようにCSS等で明確に非表示にしたり要素を削除する必要があります。
こちらのギャラリーページDEMOではモーダルを開くタイミングで変更前後の要素に同じview-transition-nameを付与することで要素ごとのトランジションを実装しています。<
Cross-document(MPA向け)の実装
MPAでのページ間トランジションは、なんとCSSを数行書くだけで有効になります。JavaScriptは不要です。
CSS
/* 遷移元・遷移先ページ両方のCSSに追記するだけ */
@view-transition {
navigation: auto;
}
これだけでChrome・EdgeとSafariではページ遷移時にクロスフェードが付きます。view-transition-name や ::view-transition-old / new といったカスタマイズもSPAと同様に使えます。
Firefoxは現時点では未対応ですが、非対応ブラウザでは普通の遷移にフォールバックするだけなので、デプロイに踏み切ること自体は問題ありません。
エラー発生や読み込み長い場合などイレギュラー時の挙動について
エラー時にはブラウザがフリーズするのではなく、通常の遷移が行われます。さらに遷移後の状態の読み込みに時間がかかってしまう場合もMPAではエラーとなり通常の遷移になります。仕様に明記されていないもののChromeの開発ツールのネットワーク回線のスロットリングでテストしたところ1秒前後でタイムアウトしてしまっているように見えました。そのためFirefoxは想定しないケースでも遷移後のページの容量が重かったりしてレスポンスが遅いケースが想定される場合であればタイムアウトをより細かく制御できるswup.jsなどの導入を検討してみてください。
一方でSPAで時間がかかってしまうケースはView Transition APIを使わない場合でも同様に変更後の状態をfetch等で取得できるまで待機する処理が入るかと思いますが、ここでは自動的にタイムアウトがかからない可能性がありますので、このケースを想定する場合はあらかじめ変更後状態の取得にタイムアウトの処理を組み込む方が安全かと思われます。