GifproGifpro

Cross-Document View Transitions落とし穴3選:CSS遷移アニメーションの作例と対策プロンプト

Cross-Document View Transitions落とし穴3選:CSS遷移アニメーションの作例と対策プロンプト

ページ遷移がついにCSSだけで滑らかに

Chrome 126でデフォルト有効化されたCross-Document View Transitionsは、同一オリジン内のページ遷移をCSSとHTMLの属性指定のみでアニメーション可能にする。これまでのJSライブラリに頼った手法と異なり、ブラウザネイティブで動作するためパフォーマンス面でも有利。しかしCSS-Tricksの記事が指摘するように、実装を始めると「思った通りに動かない」ケースに遭遇する。

本記事では、筆者が実務で遭遇した落とし穴を3つに絞り、それぞれの原因と回避策を具体的に解説する。

落とし穴1: view-transition-nameの重複が引き起こす要素のミスマッチ

遷移元と遷移先で同じview-transition-nameを持つ要素は、ブラウザが自動的に「同じ要素」と見なしてアニメーションをつなぐ。この仕様自体は直感的だが、問題は同一ページ内で複数の要素に同じ名前を付与した場合だ。

例えば、ブログの一覧ページと詳細ページで、それぞれの記事カードにview-transition-name: cardを付与すると、ブラウザは「同じcard要素が変化した」と解釈し、意図しない位置やサイズの補間が発生する。結果として、画面外のカードが突然ワープしたり、複数のカードが同時にアニメーションしてしまう。

対策: ユニークな識別子(データ属性や動的なクラス名)を組み合わせて、遷移間でマッチングさせる要素を明確に限定する。例えばview-transition-name: card-{id}のようにIDを含める。同一セッション内でIDが衝突しない設計が必須だ。

落とし穴2: CSS疑似要素のスコープとスタイルの継承問題

View Transitionsは内部的に::view-transition-old::view-transition-newといった疑似要素を生成し、これにアニメーションを適用する。ここでの罠は、これらの疑似要素が通常のDOMツリー外に生成される点にある。

開発者がページ全体のスタイルをbody#rootにスコープしている場合、疑似要素はそのスコープ外に存在するため、意図したスタイルが継承されない。特にanimation-fill-mode: forwardstransform-originの設定をミスると、遷移中に表示が崩れたり、アニメーション終了後に要素が消えたままになる。

対策: View Transitions用のスタイルは、疑似要素に対して直接指定する。例として::view-transition-old(*) { animation-duration: 0.5s; }のように、グループセレクタや個別の疑似要素を明示的にターゲットにする。ページ全体のスタイルシート内で、:rootレベルのカスタムプロパティとして定義するのも有効だ。

落とし穴3: 動的コンテンツとスクロール位置の復元競合

Safari 18.2で正式対応されたCross-Document View Transitionsだが、動的に読み込まれるコンテンツ(画像Lazy Loadや遅延スクリプト)との組み合わせで問題が顕在化する。遷移中にブラウザが古いスナップショットを表示するタイミングと、新しいページのスクロール位置復元(Scroll Restoration)が競合する。

具体例として、無限スクロール実装の一覧ページから詳細ページに遷移するとき、遷移元のスクロール位置が500pxだった場合、遷移先ページも自動的に500pxにスクロールしようとする。しかしその時点では遷移先のDOMが完全に構築されておらず、結果として画面が白く抜けたり、アニメーションが途中で停止する。

対策: document.startViewTransition()を呼び出す前に、window.scrollTo(0,0)で明示的にスクロール位置をリセットする。加えて、遷移の完了を検出するfinishイベントリスナー内で、本来のスクロール位置を復元するロジックを組む。History APIのscrollRestorationプロパティをmanualに設定しておくと、ブラウザの自動復元を上書きできる。

実装前に知っておくべき移行戦略

これらの問題を回避するには、プロジェクト初期からView Transitionsを設計に組み込むのが理想だ。しかし既存のコードベースに後付けする場合、以下の優先順位で対処すると良い。

  • 最初にview-transition-nameが重複していないか監査する。Chrome DevToolsの「Rendering」タブでView Transitionsの可視化を有効にすると、マッチング状態が確認できる。
  • 疑似要素のスタイルは::view-transition-group単位でテストし、期待通りにアニメーションするか検証する。特にtransformのスケールや位置を操作する場合は、親要素のコンテキストを意識する。
  • 動的コンテンツを含むページでは、遷移前にDOMの準備が完了していることを確認する。Lazy Load画像が多いなら、IntersectionObserverで全要素の読み込みを待ってから遷移を開始する。

2026年のView Transitionsは実用期に入った

Cross-Document View Transitionsは、Web標準としての成熟度を高めている。Baseline 2026のアップデートで主要ブラウザでのサポートが概ね揃い、CSS-Tricksの記事が指摘するような「細かな挙動の違い」も仕様として明確化されつつある。開発者に求められるのは、従来のJSアニメーションの常識を捨て、ネイティブの仕組みに合わせた設計パターンを理解することだ。

特にSPAからMPAへの回帰トレンドが進む中、View TransitionsはMPAのUXを一気に向上させる鍵となる。落とし穴を事前に把握し、適切なテストコードとともに導入すれば、ユーザー体験は劇的に改善する。

参照

理人と理子

この記事を書いた人

理人と理子

ギフプロのブログを運営している理人(リト)と理子(リコ)です!理は知性を表す漢字でもあるので、AIを連想させる名前にしてもらいました。ブログの内容はAIで作成しているところもありますが、読者の方にとって有意義な情報になるように完全自動化ではなく、人の目も通して作成しています!

Homeヘルプ