showModal() を使用して <dialog> 要素をモーダルとして開くと、ブラウザはそれを最上位レイヤに昇格させ、ドキュメントの残りの部分を不活性としてマークします。これにより、基盤となるページでのポインタ クリックとキーボード フォーカスはブロックされますが、スクロールはブロックされません。
- ポインタまたはタップ操作が
::backdropの上にあるときにスクロールすると、その下のページがスクロールされます。 <dialog>内のスクロールは、ダイアログがスクロール境界に達すると、基になるページに連鎖します。ダイアログのコンテンツがオーバーフローしない場合は、すぐに連鎖します。
CSS Overscroll Behavior の仕様に従い、overscroll-behavior は、スクロールできないスクロール コンテナ(overflow: hidden または overflow: auto を持つ要素で、コンテンツが現在オーバーフローしていないもの)を含む、すべてのスクロール コンテナ要素に適用されます。<dialog> の overscroll-behavior: contain と、dialog::backdrop の overflow: hidden および overscroll-behavior: contain を組み合わせることで、純粋な CSS を使用して、基になるページがスクロールされないようにすることができます。
実装
1. <dialog> でスクロール チェーンを抑制する
ユーザー エージェント スタイルシートは <dialog> に overflow: auto を設定し、デフォルトでスクロール コンテナにします。overscroll-behavior: contain(または none)を dialog:modal(または dialog)に適用します。
2. ::backdrop をスクロール コンテナに変換し、そのスクロールをコンテナ内に収める
デフォルトでは、dialog::backdrop は overflow: visible に設定されています。これは、スクロール コンテナではなく、overscroll-behavior を無視することを意味します。dialog::backdrop に overflow: hidden を設定して、スクロールできないスクロール コンテナにし、overscroll-behavior: contain とペア設定する必要があります。これにより、背景で行われたスクロール操作がトラップされ、下のドキュメントに到達しなくなります。
コード例
dialog:modal {
/* MANDATORY: Prevent scroll gestures inside the modal (even when its content
does not overflow) from chaining to the underlying page. */
overscroll-behavior: contain;
}
dialog::backdrop {
/* MANDATORY: ::backdrop defaults to overflow: visible (not a scroll container).
Set overflow: hidden so it becomes a non-scrollable scroll container that
honors overscroll-behavior. */
overflow: hidden;
overscroll-behavior: contain;
}
ベスト プラクティスと制約
- 必須:
<dialog>要素自体(dialog:modalセレクタを使用)とdialog::backdropにoverscroll-behavior: containを設定します。この宣言がないと、背景やダイアログ内でのスクロール操作がページに連鎖します。 - 必須:
dialog::backdropにoverflow: hidden(またはoverflow: auto)を設定して、スクロール コンテナにします。この宣言がない場合、::backdropのデフォルトはoverflow: visibleになり、overscroll-behaviorは効果がありません。 dialog::backdropまたはdialogでoverflow: clipまたはoverflow: visibleを使用しないでください。どちらの値もスクロール コンテナを確立しないため、overscroll-behaviorは適用されません。- ダイアログが開いたときに背景のスクロールをロックするために、
<html>または<body>にoverflow: hiddenまたはposition: fixedを適用しないでください。ルート オーバーフローを変更すると、ページ スクロールバーが削除され(水平方向のレイアウト シフトが発生)、ページ スクロール位置がリセットまたはジャンプし、基盤となるページのposition: sticky要素が破損する可能性があります。
代替戦略
overscroll-behavior CSS プロパティは、コンテンツがオーバーフローするスクロール コンテナのすべての主要なブラウザでサポートされていますが、スクロール不可のスクロール コンテナで overscroll-behavior を尊重することは、機能検出できない新しい仕様です。
@supports (overscroll-behavior: contain) または CSS.supports('overscroll-behavior', 'contain') を使用して、スクロール不可のコンテナのサポートを機能検出しないでください。最新のブラウザはすべて overscroll-behavior: contain プロパティ構文をサポートしており、コンテンツがオーバーフローした場合にのみ適用される場合でも true を返します。
代わりに、スクロール不可のスクロール コンテナでのスクロール コンテインメントをプログレッシブ エンハンスメントとして扱います。
- スクロール不可のスクロール コンテナで
overscroll-behaviorをサポートするブラウザでは、dialog::backdropの上でも<dialog>の内部でも(コンテンツがオーバーフローするかどうかにかかわらず)、バックグラウンド ページのスクロールが完全に防止されます。 - スクロール不可のスクロール コンテナで
overscroll-behaviorをまだサポートしていないブラウザでは、ダイアログ独自のコンテンツがオーバーフローしてスクロール可能になると、dialogのoverscroll-behavior: containによってスクロール チェーンが防止されます。一方、showModal()は引き続きキーボード フォーカスをトラップし、バックグラウンド ドキュメントをinertとしてマークします。 - プログレッシブ エンハンスメントに依存することは、
overflow: hiddenまたはposition: fixedを<html>または<body>に適用する従来の回避策よりも推奨されます。これは、ルート スクロールバーを削除したり、水平レイアウト シフトを引き起こしたり、ページ スクロール位置をジャンプさせたり、基になるページのposition: sticky要素を破損したりしないためです。