\n\n\ncss\n.modal {\n view-transition-name: app-modal;\n}\n@keyframes modal-out {\n to { transform: scale(0."}},{"@type":"Question","name":"どのような場面で役立ちますか?","acceptedAnswer":{"@type":"Answer","text":"ネイティブアニメーション、ネイティブアクセシビリティ(<dialog> 経由)、startViewTransition 1回呼び出しを超えるオーバーヘッドゼロを求める場面で、カスタムモーダルライブラリ(React Modal、Reach Dialog、Headless UI Dialog)を置き換える用途。"}}]}

View Transitions によるモーダル開閉

壊れやすい portal ベースのアニメーションライブラリをネイティブ View Transitions に置き換え、DOM 順序とアクセシビリティを尊重したスムーズな開閉を実現。

UI Patterns

詳細な説明

3フェーズのモーダルライフサイクル

洗練されたモーダルアニメーションには (1) バックドロップのフェードイン、(2) ダイアログのスケール+フェードイン、(3) ページ全体の控えめな後退、の協調が必要です。View Transitions API は (1) と (3) を無料でやってくれます。あなたが書くのは (2) だけ。

<dialog id="dlg" class="modal">…</dialog>
<button onclick="open()">Open</button>
<script>
  function open() {
    document.startViewTransition(() => {
      document.getElementById('dlg').showModal();
    });
  }
</script>
.modal {
  view-transition-name: app-modal;
}
@keyframes modal-out {
  to { transform: scale(0.96) translateY(8px); opacity: 0; }
}
@keyframes modal-in {
  from { transform: scale(0.96) translateY(8px); opacity: 0; }
}
::view-transition-old(app-modal) {
  animation: 180ms ease-in both modal-out;
}
::view-transition-new(app-modal) {
  animation: 240ms cubic-bezier(0.16, 1, 0.3, 1) both modal-in;
}

<dialog> + View Transitions が勝つ理由

ネイティブ <dialog> 要素はフォーカストラップ・Esc で閉じる・スクロールロックを自動処理します。View Transitions は視覚的振り付けを担当します。この組み合わせは、ほとんどのユースケースで React Modal/Headless UI Overlay スタック全体を、依存関係ではなく約12行のコードで置き換えます。

クロージングアニメーション

閉じる際も同じラッパーを呼び出します:

function close() {
  document.startViewTransition(() => {
    document.getElementById('dlg').close();
  });
}

ダイアログがスナップショットから消えるため、::view-transition-old(app-modal) ルールが自動発火します。

アクセシビリティ:prefers-reduced-motion

カスタム keyframes は必ずメディアクエリでラップし、reduced motion を要求するユーザーには即時切替(アニメーションなし)を提供します:

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(app-modal),
  ::view-transition-new(app-modal) {
    animation-duration: 0ms !important;
  }
}

ユースケース

ネイティブアニメーション、ネイティブアクセシビリティ(&lt;dialog&gt; 経由)、startViewTransition 1回呼び出しを超えるオーバーヘッドゼロを求める場面で、カスタムモーダルライブラリ(React Modal、Reach Dialog、Headless UI Dialog)を置き換える用途。

試してみるView Transitions API ジェネレーター

フルツールを開く