この記事はウェブクルー Advent Calendar 2025 の16日目の記事です。
昨日は @wc_sangen さんの「【2025年】私とAIコーディング」でした。
HTML の dialog 要素がすごい!モダンなモーダル UI の作り方
ものすごくAIに記事書かせてます。
Web 開発で頻繁に必要となるモーダルダイアログ。これまでは JavaScript ライブラリを使ったり、自前で複雑な実装をしたりするのが一般的でした。しかし、HTML にはネイティブでダイアログ機能を提供する<dialog>要素が用意されており、これを使うことで驚くほど簡単かつアクセシブルなモーダル UI を実装できます。
dialog 要素とは?
<dialog>要素は、インタラクティブな UI コンポーネント(ダイアログボックス、インスペクター、ウィンドウなど)を表現するための HTML 要素です。JavaScript の API と組み合わせることで、簡単に表示・非表示を制御できます。
dialog 要素のメリット
-
ネイティブ実装でシンプル:
- 追加のライブラリは不要です。HTML に
<dialog>タグを書くだけで、基本的なダイアログが完成します。 - JavaScript からの操作も
.showModal()や.close()といった直感的なメソッドで行えます。
- 追加のライブラリは不要です。HTML に
-
アクセシビリティの向上:
-
showModal()でダイアログを開くと、自動的にダイアログ以外の要素へのフォーカスが無効になります。これにより、スクリーンリーダーの利用者がダイアログ内のコンテンツに集中できます。 -
showModal()を呼び出すと、ブラウザが自動的にaria-modal="true"を要素に設定します。これにより、支援技術に対してモーダルダイアログであることが明確に伝わります。 -
Escキーを押したり、ダイアログの背景(::backdrop)をクリックしたりすると自動的にダイアログが閉じる機能も組み込まれています。
-
-
最前面への表示:
-
z-indexの管理に悩まされることはありません。showModal()で表示されたダイアログは、自動的にビューポートの最前面に表示されます。
-
基本的な使い方
HTML
<!-- ダイアログ本体 -->
<dialog id="myDialog">
<h2>お知らせ</h2>
<p>dialog要素はとても便利です!</p>
<button id="closeButton">閉じる</button>
</dialog>
<!-- ダイアログを開くボタン -->
<button id="openButton">ダイアログを開く</button>
JavaScript
const dialog = document.getElementById("myDialog");
const openButton = document.getElementById("openButton");
const closeButton = document.getElementById("closeButton");
// ボタンクリックでダイアログを表示
openButton.addEventListener("click", () => {
dialog.showModal(); // モーダルとして表示
});
// 閉じるボタンでダイアログを閉じる
closeButton.addEventListener("click", () => {
dialog.close();
});
// Note: モダンブラウザでは、<dialog>を showModal() で表示した場合、
// デフォルトで背景のクリックや Esc キーでダイアログを閉じることができます。
// もし、何らかの理由でこの挙動を無効にしたい場合や、
// 未対応や古いブラウザへのフォールバックが必要な場合にのみ、
// 以下の様なJavaScriptによる実装を検討します。
/*
dialog.addEventListener('click', (event) => {
if (event.target === dialog) {
dialog.close();
}
});
*/
aria-modal 属性の詳細
aria-modal属性は、WAI-ARIA(Web Accessibility Initiative - Accessible Rich Internet Applications)仕様の一部で、モーダルダイアログの動作を支援技術に伝えるための重要な属性です。
aria-modal="true" の役割
-
フォーカス管理の通知:
- 支援技術(スクリーンリーダーなど)に対して、現在表示されているコンテンツがモーダルダイアログであり、他の要素へのアクセスが制限されていることを明確に伝えます。
-
コンテンツの範囲指定:
- スクリーンリーダーの利用者に対して、現在操作可能なコンテンツの範囲がダイアログ内に限定されていることを示します。
- これにより、ユーザーは背景のコンテンツを無視して、ダイアログ内の要素のみに集中できます。
-
ナビゲーションの制御:
- 一部の支援技術では、
aria-modal="true"が設定されている要素の外側への移動を自動的に制限します。
- 一部の支援技術では、
dialog 要素での自動設定
<dialog>要素では、showModal()メソッドが呼び出されると、ブラウザが自動的に以下の処理を行います:
-
aria-modal="true"属性の設定 - ダイアログ外の要素への
inert属性の適用(フォーカス移動とクリックの無効化) - 適切なフォーカス管理
従来の手動実装との比較
従来のカスタムモーダル実装では、開発者が手動で以下を管理する必要がありました:
// 従来の手動実装例
function showCustomModal(modalElement) {
// 手動でaria-modal属性を設定
modalElement.setAttribute("aria-modal", "true");
// 背景要素のフォーカスを無効化
document.querySelectorAll("body > *:not(.modal)").forEach((el) => el.setAttribute("inert", ""));
// フォーカストラップの実装
// キーボードナビゲーションの制御
// ... 複雑な実装が必要
}
一方、<dialog>要素なら:
// dialog要素での実装
dialog.showModal(); // これだけで全て自動処理される
この自動化により、アクセシビリティの実装ミスを大幅に減らすことができ、より確実にアクセシブルなモーダル UI を提供できます。
ブラウザサポート状況
<dialog>要素は、モダンブラウザで広くサポートされています。詳細なサポート状況については、Can I Use で確認できます:
Browser Support: https://caniuse.com/?search=dialog
主要ブラウザでのサポート状況:
- Chrome: 37+ (2014 年〜)
- Firefox: 98+ (2022 年〜)
- Safari: 15.4+ (2022 年〜) ※一部機能に制限あり
- Edge: 79+ (2020 年〜)
Safari での制限事項
Safari では<dialog>要素の基本機能はサポートされていますが、以下の制限があります:
-
::backdrop疑似要素のスタイリング:Safari 15.4〜16.3 では::backdrop疑似要素が完全にサポートされておらず、背景のオーバーレイをカスタマイズできない場合があります -
closedby属性の未対応:Safari ではclosedby属性がサポートされていません。この属性は、Esc キーや背景クリックによる自動クローズの動作を制御するためのものですが、Safari では手動で JavaScript を使って実装する必要があります - 一部のアクセシビリティ機能:フォーカストラップやキーボードナビゲーションが他のブラウザと比べて不完全な場合があります
-
アニメーション対応:
dialog要素の表示・非表示時のアニメーション処理が制限される場合があります
closedby属性について:
<!-- Chrome/Firefox では動作するが、Safari では無効 -->
<dialog closedby="any">
<p>背景クリックまたはEscキーで閉じられます(Safari以外)</p>
</dialog>
<dialog closedby="none">
<p>自動クローズを無効化(Safari以外)</p>
</dialog>
<dialog closedby="closerequest">
<p>closerequestイベントが発生した時のみ閉じられます</p>
<button onclick="closeButton.close()">閉じる</button>
</dialog>
closedby="closerequest"の場合、以下の方法でダイアログを閉じることができます:
- JavaScript の
.close()メソッドを明示的に呼び出す - Escキーを押す(これにより
closerequestイベントが発火し、ダイアログが閉じられる) - 背景クリックでは閉じられない(
closerequestイベントが発火しないため)
const dialog = document.querySelector('dialog[closedby="closerequest"]');
// Escキーまたは.close()メソッドで閉じることが可能
dialog.addEventListener('closerequest', () => {
console.log('closerequestイベントが発火しました');
// イベント処理後、自動的にダイアログが閉じられる
});
これらの制限を回避するには、CSS や JavaScript でのフォールバック実装を検討することをお勧めします。
注意点として、一部の古いブラウザでは対応していないため、必要に応じてポリフィルの使用を検討してください。
まとめ
HTML の<dialog>要素は、モダンな Web 開発において非常に強力なツールです。シンプルさ、アクセシビリティ、そしてネイティブならではの安定性を兼ね備えており、これまでモーダル UI の実装に費やしていた多くの時間と労力を削減してくれます。ぜひ次のプロジェクトから活用してみてください。
参考
明日は @yo-shibata さんの投稿になります。よろしくお願いします。