モーダルはネイティブの dialog で:無料で付いてくるものが多い
自前のモーダルはフォーカストラップ、ESC、スクロール固定、フォーカス復帰を全部書くことになる。dialog と showModal なら全部入りで ::backdrop も使える。
モーダルを作るときの既定は変わりました。<div class="overlay"> ではなく、ネイティブの <dialog> と showModal() です。
showModal が無料でくれる 4 つ
showModal() は open 属性とは別物で、要素をトップレイヤーに載せます。その結果、普段は自分で書く 4 つが組み込みの挙動になります。
- フォーカストラップ:Tab が背後のページへ抜けず、支援技術から見て背景は
inert - ESC で閉じる:
keydownを自分で監視せず、閉じたときのイベントはclose - スクロール固定:背後の文書が止まり、
bodyにoverflow: hiddenを足す必要もない - フォーカス復帰:閉じるとブラウザが開いた要素へフォーカスを戻す
トップレイヤーは z-index の問題も同時に片づけます。モーダルは常に最前面で、overflow: hidden の祖先に切り取られず、ヘッダーに大きな z-index を足す必要もありません。
唯一の罠は ::backdrop
覆いは dialog の背景ではなく、同じ名前の擬似要素です。
dialog::backdrop {
background: color-mix(in srgb, var(--c-ink) 60%, transparent);
}
::backdrop はトップレイヤーの独立したボックスなので、dialog に書いたカスタムプロパティを継承しません。サイトのトークンを読ませたいなら dialog ではなく :root に定義します。ここが一番混乱しやすいところです。
自前の層が正しい場合
このサイトのツール画面には純 CSS の ui-overlay(結果パネル、読み込み中の表示)があります。あれは表示層であってモーダルではありません。閉じ込めるフォーカスも、操作もなく、スクロールして流れ去って構わないものです。本当のモーダル(削除の確認など)は dialog を使います。
ネイティブ要素で足りるなら自前で作らない。自作の理由は見た目だけにしておく。

コメント
…