Web標準のモーダルを実装しよう
苅田 玻優世
Modalを実装する時ってどんなライブラリを使おうか悩んだりしますよね。
しかし、いまではhtmlの標準でdialogタグというModal Dialogを実装するタグがあり、Modalの機能をある程度網羅してくれています。
今日はそんなdialogタグを、実用段階で使えるようにしていきましょう。
標準挙動(jsなし)
なるべくjsのカスタムをしなくてもいいように標準挙動を見てみましょう。
See the Pen Default dialog by Hayuse (@dtweqbgd-the-vuer) on CodePen.
See the Pen Untitled by Hayuse (@dtweqbgd-the-vuer) on CodePen.
特徴
- 「開く」動作は実装されていない。
- open属性がつくとdialogが開く
- 「閉じる」動作は実装されている。
- dialogで囲っているformにmethod="dialog"をつけることでformがサブミットされると閉じられます。
- dialogタグにclosedby="any"をつけることでモーダル外をクリックで閉じる挙動追加
では、開く動作はどうするのか?ですが、ここはjavascriptが必要なようです。
しかし、デフォルトのメソッドが用意されているので、比較的用意です。
開く挙動の追加(jsあり)
標準で用意されているメソッドは
- showModal()
- show() ←使わないよ
この二つです。
しかし、今回はshow()は使わずpopover属性を使用します。理由は後述します。
See the Pen Untitled by Hayuse (@dtweqbgd-the-vuer) on CodePen.
特徴
- showModal()は:backdropが標準でつくいわゆるモーダルを表示
- popoverは非モーダルを表示
- 開いた時に自動でdialog内の操作可能なDOMにフォーカス。
- showModal()はTabはモーダル内での移動。
- popoverはTabはモーダル内での移動が終わり次第メインの次の操作可能DOMに遷移
だいぶもう実用できる段階まで来ました。
あとはよくあるユースケースごとにみていきましょう。
アニメーション付与(追加のjsなし)
開く用のjsは必須ですが、アニメーション自体はもうcssのみで実装する時代です。
See the Pen dialog アニメーション by Hayuse (@dtweqbgd-the-vuer) on CodePen.
特徴
- @keyframeを使わなくても@starting-styleとtransition allow-discreteを使えばイン、アウト両方のアニメーションがつけれる。(2025/12/9現在:allow-discreteはFirefoxは対象外です)
- displayとoverlayは脳死でtransitionつければ動く。(ちゃんと意味はあるから詳しくはMDN)
複数の非モダールダイアログ(jsなし)
固定箇所でモーダルを表示する場合、ボタンの近く(相対位置)に表示する場合の2パターンです。
See the Pen 複数の非モーダルダイアログ by Hayuse (@dtweqbgd-the-vuer) on CodePen.
特徴
- jsは一切不要
- anchor-positioningでjsを使わずに相対位置に非モーダルを表示
- 排他制御の実装(複数同時に開かない)
なぜshow()メソッドを使わないのか?
理由は非モーダルにおいてはpopoverAPIを使った方がメリットが多いからです。
主なメリットはこちら
- 排他制御が可能(popover="auto")
- show()メソッドは排他制御は自前でやらないとなので、複数のdialogがある場合にたくさん出せてしまいます。
- togglePopover()が便利すぎる。(※デフォルトでtoggleです)
- 一つの非モーダルに対して複数箇所から操作が可能(同期もしてくれる)
- 排他制御をオフにもできる( popover="manual")
- 複数出そうと思えば出せる
dialogのshow()メソッドとpopoverAPIについては色々議論があるようです。
個人的には非モーダルはpopoverでいいかなと思います。
dialogタグはセマンティクス*的に使った方がいいかなという印象です。
*セマンティクス(Semantics) : セマンティクスとは、コードの断片の意味を指します。~「その HTML 要素には、どのような目的や役割があるのか?」~ 参考
showModal()はどうなの?
こちらは使う価値ありだと思われます。
showModal()の場合、:backdropが出るのも大事ですがそれより、フォーカストラップ*が機能することが大きいように思えます。
本来のモーダルの在り方として、ユーザーの操作を強制する意図がありますので、モーダル外にフォーカスされないよう制限することは意義のあるものと言えます。(W3C参考)
*フォーカストラップ:フォーカストラップ(またはループ)とは、ウェブページをキーボードで操作する際にフォーカスをとある領域からはみ出さないようにすることです。フォーカス可能な要素を抽出してその中をループすることで実現ができます。参考
まとめ
モーダルはdialog + showModal()
非モーダルは dialog + popoverAPI
これが最適解かなと思います。(反論受け付けます)
どちらもWeb標準の機能ですので、キーボード操作や、アクセシビリティの観点から見ても積極的に使うべき内容だと思います。
ぜひ参考にしていただけると幸いです。
参考
dialog要素と@starting-styleでふわっと表示させる方法
【HTML】popover と dialog との関係性について調べてみた
CSS Anchor Positioning 仕様の紹介
dialog MDN
popoverAPI MDN
苅田 玻優世/ フロントエンドエンジニア
日々スムーズなフロント開発について考えています。
趣味はPCいじりや何かを作ることが好きで、Raspberrypiとかのマイコンもいじったりしています。
(動画を作ったりするのも好きです)
好きな言語はTypescript!!
