Web で利用されるモーダルダイアログについて、その実装やアクセシビリティについて掘り下げ、それらの実装などについてまとめます。内容は著者の理解に基づいており、正確性を保証するものではありません。
詳しくは ARIA-APG を参照ください。
Modal Dialog Examplehttps://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/dialog/
細かい実装については次の記事がとても参考になります。
アクセシブルなモーダルダイアログの実装について考えるhttps://zenn.dev/yend724/articles/20220511-pc51v32llyzu8kws
また、dialog
要素はすでに baseline 2020 に含まれているためdialog
要素も使うことができますが、その構造や挙動についても確認するため、dialog
要素を使わない場合を考えます。
Dialog element | Can I use... Support tables for HTML5, CSS3, etchttps://caniuse.com/dialog
Wkipedia でモーダルは
何らかのウィンドウの子ウィンドウとして生成されるサブ要素のうち、ユーザーがそれに対して適切に応答しない限り、制御を親ウィンドウに戻さないもの
とされています。
モーダル、ダイアログ、モーダルダイアログ、など様々な名前で呼ばれることもありますが、ここではそれらの違いを明確にせず、ダイアログと呼びます。
ダイアログを構成する基本的な要素です。構造の概略としては以下のようになります。
1- オーバーレイ
2 - コンテナ
3 - タイトル
4 - 説明
5 - コンテンツ
もしくは
1- オーバーレイ
2- コンテナ
3 - タイトル
4 - 説明
5 - コンテンツ
ダイアログの背景として用いられることが多いです。半透明の要素を全画面に表示し、ダイアログ以外のコンテンツを操作できないようにします。
この要素の階層構造はコンテナの親要素でも、兄弟要素でも良いようです。react-aria
やARIA-APG
ではコンテナの親要素に設定しています。radix-ui
では兄弟要素に設定しています。
オーバーレイをクリックするとダイアログを閉じることができるようにする場合もあります。UI ライブラリなどではそのようなオプションが提供されていることがありますが、その微妙な挙動などは微妙に異なります。
例えば、 radix-ui
では押下時にダイアログを閉じるようになっていますが、react-aria
ではクリックでダイアログを閉じるようになっています。
ダイアログの親要素です。
ダイアログのタイトルです。h2
が見出し要素として使われることが多いですが、推奨される定義は見つかりませんでした。
ダイアログの説明です。必須ではありませんが、ダイアログの内容を説明する必要がある場合は設定します。
ダイアログのコンテンツです。フォームやボタンなど、ユーザーが操作する要素が含まれます。 基本的にダイアログを閉じるアクションを持つ要素を含める必要があります。
アクセシビリティやユーザビリティを向上させるために、いくつかの注意があります。
基本的にはトリガーした要素にフォーカスを戻します。
次のようにダイアログからダイアログを経由する場合は最初のダイアログ A を開いたトリガーボタン A にフォーカスを戻します。(ARIA-APG のdialog1
,dialog3
の例)
最初のフォーカス可能要素がダイアログの下部にあり、フォーカスによってスクロールされてコンテンツが順序通りに見れなくなってしまう場合は、フォーカスさせる必要はありません。(ARIA-APG のdialog2
の例)
もし、確認ダイアログのようなもので OK ボタンをユーザーが押すことが期待される場合は、OK ボタンにフォーカスさせることも考えられます。必ずしも最初の要素にフォーカスさせる必要はありません。(ARIA-APG のdialog3
の例)
Modal Dialog Examplehttps://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/dialog/
ダイアログ内でのキーボード操作についても考慮する必要があります。 Tab でフォーカスを移動可能ですが、ダイアログ内にロックされ、ループするような挙動になります。
支援技術に対応してアクセシビリティを向上させるために、WAI-ARIA で仕様が定められています。
基本的な構造は以下のようになります。
1<div class="overlay" aria-hidden="true"></div>
2<div
3 role="dialog"
4 aria-modal="true"
5 aria-labelledby="dialog-title"
6 aria-describedby="dialog-description"
7>
8 <h2 id="dialog-title">タイトル</h2>
9 <p id="dialog-description">説明</p>
10 <button>OK</button>
11 <button>キャンセル</button>
12</div>
支援技術にダイアログであることを示します。
他にもrole="alertdialog"
などの類似要素があります。
支援技術にダイアログであることを示し、それ以外のコンテンツを不活性要素として扱います。
しかし、aria-modal
をサポートしていないアクセシビリティサービスがあるようで、aria-hidden も適用した方が良いかもしれません。
ダイアログ以外のコンテンツを隠すために、ダイアログが表示されている間はダイアログ以外の要素にaria-hidden="true"
を設定します。
ダイアログのタイトルを示すために、ダイアログの見出し要素の ID を指定します。
ダイアログの説明を示すために、ダイアログの説明要素の ID を指定します。説明が省略できる場合は省略しても構いません。
ユーザー体験を考える上で、Tab のフォーカス移動がダイアログの後ろのコンテンツに移動しないようにしたり、ダイアログを表示した際に適切な要素にフォーカスするなど、考えるべき点が多い要素です。 独自実装が可能な Web の世界で自前で作成する場合は、より一般的で標準化されたインタラクションを実現したいと思いました。
Modal Dialog Examplehttps://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/dialog/
Dialoghttps://react-spectrum.adobe.com/react-aria/Dialog.html
Dialog – Radix Primitiveshttps://www.radix-ui.com/primitives/docs/components/dialog