代表的な面接トピック

View Transition API を使ってマルチページアプリをプログレッシブエンハンスメントするにはどうすればよいですか?

フロントエンド普通
Offer.cc 編集チーム公開日 更新日

質問

サーバーレンダリングされたマルチページサイトを運用しており、サポートされているブラウザではシームレスな視覚的トランジションを提供しつつ、古いブラウザ、視覚的動きの抑制(reduced-motion)を好むユーザー、および遷移失敗時にも通常の挙動を維持したいと考えています。どのように設計しますか?

質問とシナリオ

このサイトでは、サーバーによってレンダリングされる同一オリジンのページ間で通常のリンクを使用しています。目標は、サポートされている環境では連続的なトランジションを実現し、それ以外のすべての環境ではネイティブなナビゲーションを維持することです。優れた回答では、両方のトランジションメカニズム、更新失敗時の処理、履歴ナビゲーション、フォーカス、スクロール位置、および視覚的動きの抑制設定について網羅します。

面接官がテストしていること

  • 候補者が document.startViewTransition() を使用した同一ドキュメントの更新と、@view-transition でオプトインされたクロスドキュメントのナビゲーションを区別できるか。
  • この API がリンク、履歴、サーバーレンダリングの代替ではなく、エンハンスメントレイヤー(拡張層)であることを理解しているか。
  • 機能検出、障害フォールバック、および prefers-reduced-motion を安全に適用できるか。
  • トランジション疑似要素、フォーカス管理、低速デバイス、および中断されたナビゲーションをテストできるか。

最初に確認すべき明確化のための質問

ナビゲーションが常に同一オリジンであるか、iframe が関係しているか、共有要素のアニメーションが必要か、クライアントルーターが既に存在するかを確認します。ターゲットブラウザ、継続時間の制限、シンプルなフェードで十分か、そしてユーザーがモーションを無効にした場合にプロダクトがどう振る舞うべきかを明確にします。クロスドキュメントトランジションでは、関与する両方のドキュメントがオプトインしており、ブラウザがその機能をサポートしている必要があります。クロスオリジン間のナビゲーションメカニズムではありません。

30秒の回答フレームワーク

ネイティブリンクとサーバーナビゲーションをベースラインとして維持し、その上でプログレッシブにトランジションを追加します。ページ内の更新には、startViewTransition の機能検出を行い、DOM の更新をラップします。同一オリジンのマルチページナビゲーションには、両方のドキュメントで @view-transition をオプトインします。更新が失敗した場合でも、ページは利用可能な状態を維持し、エラーは既存の UI で処理される必要があります。モーションはトランジション疑似要素のみに属し、動きの抑制設定を尊重し、フォーカス、スクロール、または履歴のセマンティクスを乗っ取ることはありません。非サポートブラウザ、フォールバック、戻る/進む、低速ネットワーク、および中断されたナビゲーションをテストします。

ステップごとの詳細解説

  1. アニメーションなしのベースラインを構築する。 リンク、フォーム送信、サーバーレスポンス、およびエラーページは独立して動作する必要があります。アニメーションを模倣するためにすべてのナビゲーションをインターセプトしないでください。
  2. 同一ドキュメントの更新を処理する。 フィルタリングやローカルな状態変更には、document.startViewTransition を検出します。サポートされていない場合は、同じ更新関数を直接実行します。コールバックが失敗した場合は、既存のエラー状態を表示します。
  3. クロスドキュメントのナビゲーションを処理する。 同一オリジンのページに @view-transition { navigation: auto; } を追加して、ブラウザがナビゲーション中にトランジションを作成できるようにします。startViewTransition は呼び出さないでください。オプトインがない場合やサポートされていない場合は、通常のナビゲーションにフォールバックします。
  4. 視覚的スコープを制限する。 安定した対応関係を持つ要素にのみ view-transition-name を割り当てます。短く中断可能なフェードには ::view-transition-old::view-transition-new を使用します。
  5. アクセシビリティを保護する。 @media (prefers-reduced-motion: reduce) の下ではモーションを無効化または短縮します。ナビゲーション後は、新しいページのメイン見出しまたは意図した別のターゲットにフォーカスを配置します。スクリーンショットにセマンティックな状態を持たせてはいけません。
  6. ランタイム状態を処理する。 戻る、進む、更新、ネットワーク障害、連打、およびページ離脱には通常の処理結果が必要です。トランジションは視覚的なタイミングを変更するだけであり、URL、キャッシュ、権限、または送信のセマンティクスを変更するものではありません。

高品質な回答例

ネイティブナビゲーションのベースラインと、オプショナルのアニメーションレイヤーを分離します。同一ドキュメントの更新では、すべてのブラウザが単一の update 関数を呼び出し、サポートしているブラウザは document.startViewTransition(update) を呼び出し、その他のブラウザは update を直接呼び出します。サーバーレンダリングされたマルチページナビゲーションでは、同一オリジンのページに @view-transition { navigation: auto; } を含めます。リンクは本物のままであり、クロスオリジンのサポートは前提としません。

アニメーションレイヤーは視覚的な連続性のみを提供します。安定した view-transition-name 値で一致する要素を識別し、デフォルトでは短いフェードを使用し、動きの抑制設定がある場合は無効にします。新しいドキュメントは、通常のレスポンスを通じてフォーカス、スクロール、エラーを引き続き処理します。テストでは、未サポート環境、コールバックエラー、戻る/進む、連打、低速 CPU、低速ネットワーク、タブの切り替え、および動きの抑制設定を対象とします。主な参考文献は、MDN の View Transition API および startViewTransition ドキュメント、そして Chrome for Developers のクロスドキュメントガイドです。

よくある間違い

  • クロスドキュメントナビゲーションに対して startViewTransition を呼び出すこと。これは同一ドキュメント更新用であり、ナビゲーションと CSS のオプトインによってクロスドキュメントの処理が開始されます。
  • すべてのリンクをスクリプトでブロックし、キーボード操作、リンクのコピー、戻るナビゲーション、および no-script アクセスを損なうこと。
  • 機能検出やネイティブフォールバックを行わずに、ブラウザ間や iframe 全体で同じサポートがあると思い込むこと。
  • 多数の要素に重複した名前を付けたり、アニメーションを長くしすぎてスナップショットの競合や見当識障害を引き起こしたりすること。
  • 進む方向のクリックのみをテストし、失敗したレスポンス、戻る/進む、動きの抑制、および中断されたトランジションを無視すること。

フォローアップ質問と回答

同一ドキュメントの更新コールバックが失敗した場合はどうなりますか?

DOM の更新とエラー状態を、独立して実行可能な関数として維持します。ViewTransition の例外をキャッチするのは、ログ記録と視覚的状態の収束のためです。ビジネスエラーは依然として既存の UI を使用し、アニメーションの例外がデータ更新をブロックしてはなりません。

クロスドキュメントトランジションがナビゲーションセマンティクスを変更していないことをどのように証明しますか?

サポートされているブラウザとサポートされていないブラウザで、URL、履歴スタック、更新、コピーしたリンクからのアクセス、キーボード操作、フォーカスターゲット、およびサーバーエラーページを確認します。CSS トランジションを無効にした場合でも、ページの結果は同一である必要があります。

共有要素のアニメーションを避けるべきなのはどのような場合ですか?

アイデンティティが不安定な場合、リストの並べ替えが頻繁に発生する場合、コンテンツの動きが激しい場合、またはユーザーが即座に状態の場所を把握する必要がある場合は、シンプルなフェードを使用するか、モーションを使用しないようにします。視覚的なメリットがフォーカス、パフォーマンス、および理解のコストに見合わない場合は、ネイティブの動作を維持します。

公開情報ソース

関連する質問