HTMLの<dialog>要素とCSSで、モーダル・ダイアログ ボックスを実装する方法と注意点
Post on:2019年5月13日
sponsorsr
モーダル・ダイアログ ボックスはWebサイトやスマホアプリでよく見かけます。しかし、その実装方法は何通りもあります。その多くはWebを視覚的にナビゲートしないユーザーにとっては実質的にモーダルボックスを使用できず、アクセシブルに実装するのは困難でした。
HTML 5.2で登場した新しい<dialog>要素はこの問題を解消し、実装方法を迷うことなくモーダルやダイアログ ボックスを利用できるようにするものです。
<dialog>要素で、モーダル・ダイアログ ボックスを実装する方法と注意点を紹介します。

下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
- HTML 5.2の新機能: モーダル・ダイアログ ボックスを実装するための<dialog>要素
- <dialog>要素の基本機能
- <dialog>要素のスタイル
- <dialog>要素のコントロール
- <dialog>要素で実装するモーダルボックス
HTML 5.2の新機能: モーダル・ダイアログ ボックスを実装するための<dialog>要素
昨年暮れに勧告されたHTML 5.2で、モーダル・ダイアログ ボックスを実装するための<dialog>要素が新しく加わりました。
参考: HTML 5.2の新機能・削除された機能、変更された記述ルールのまとめ
一見したところ、それはかなり簡単に思えるかもしれませんが、私は<dialog>要素を試しているうちに、見逃しやすい素晴らしい機能がいくつかあることに気がつきました。
この記事の最後に<dialog>要素で実装したデモを掲載していますが、先に動作を確認したい方は下記のデモページをチェックしてください。

モーダル・ダイアログ ボックスの基本的なマークアップは下記のようになります。
| 1 2 3 | <dialog open>   ネイティブのダイアログ ボックス </dialog> | 
open属性は、モーダルが可視であることを意味します。open属性がなければ、モーダルを表示するためにJavaScriptを使用するまでモーダルは表示されません。
モーダルはスタイルシートを適用する前は、下記のようにレンダリングされます。

ネイティブのダイアログ ボックス
モーダルはページ上に絶対配置で、他のコンテンツの前に表示され、水平方向の中央に配置されます。モーダルの幅はデフォルトでは、その中のコンテンツに依存されます。
<dialog>要素の基本機能
JavaScriptには、<dialog>要素を扱うためのメソッドとプロパティがいくつかあります。最も重要な2つのメソッドはshowModal()とclose()です。
| 1 2 3 4 5 6 7 | const modal = document.querySelector('dialog'); // モーダルを表示する (open属性を与える) modal.showModal(); // モーダルを隠す (open属性を削除する) modal.close(); | 
showModal()を使用してモーダルを開くと、ページに背景が追加され、モーダル以外のコンテンツとのユーザーのやり取りがブロックされます。デフォルトでは、この背景は完全に透明ですが、CSSで表示することができます(詳細は後述)。
キーボードのescを押すとモーダルは閉じますが、close()メソッドをトリガーにして閉じるボタンを用意することもできます。
もう一つ便利なメソッドがあります。show()を使用すると、モーダルは表示されますが、付随する背景はありません。ユーザーはモーダル ボックスの外側に表示されているコンテンツと引き続きやり取りができます。
ブラウザサポートとポリフィル
現在のところ、<dialog>の動作はChromeでのみサポートされています。Firefoxはデフォルトのスタイルを提供しますが、フラッグ(サポートされていないけれど、使用可能)の状態です。私はFirefoxがすぐにサポートすると考えています。
ありがたいことに、JavaScriptビヘイビアとスタイルシートにデフォルトスタイルを提供するポリフィル「dialog-polyfill」があります。 npmにインストールするか、通常の古い<script>タグを使用してください。ポリフィルを使用すると、IE9以上で動作します。
ポリフィルを使用する場合は、ページ上の各モーダルを初期化する必要があります。
| 1 | dialogPolyfill.registerDialog(modal); | 
注意点は、ブラウザのネイティブ動作ではないということです。
<dialog>要素のスタイル
モーダルが開閉できるのは素晴らしいですが、デフォルトの動作はシンプルです。モーダルにスタイルを加えることは他の要素に加えるのと同じくらい簡単です。
背景は、新しい::backdrop擬似要素でスタイルできます。
| 1 2 3 4 5 6 7 8 9 10 11 | dialog {   padding: 0;   border: 0;   border-radius: 0.6rem;   box-shadow: 0 0 1em black; } dialog::backdrop {   /* 背景を半透明のブラックにする */   background-color: rgba(0, 0, 0, 0.4); } | 
ただし、ポリフィルを使用する古いブラウザの場合、この::backdrop擬似要素は機能しません。その代わりに、ポリフィルではモーダルの直後に.backdrop要素を追加します。下記のようにCSSで背景を記述します。
| 1 2 3 | dialog + .backdrop {   background-color: rgba(0, 0, 0, 0.4); } | 
スタイル用のフックが必要なため、もう少しマークアップを追加します。モーダル ボックスの一般的なアプローチは、ヘッダとボディとフッタに分割することです。
| 1 2 3 4 5 6 7 8 9 10 | <dialog id="demo-modal">   <h3 class="modal-header">A native modal dialog box</h3>   <div class="modal-body">     <p>Finally, HTML has a native dialog box element! This is fantastic.</p>     <p>And a polyfill makes this usable today.</p>   </div>   <footer class="modal-footer">     <button id="close" type="button">close</button>   </footer> </dialog> | 
これにいくつかのCSSを記述することで、あなたが望むモーダル ボックスの見た目を作ることができます

スタイルを適用したモーダル ボックス
<dialog>要素のコントロール
モーダル ボックスを使用するユーザーからフィードバックを必要とすることがあると思います。モーダルを閉じる時に、close()メソッドで文字列値を渡すことができます。この値はモーダルのDOM要素のreturnValueプロパティに割り当てられているため、参照することができます。
| 1 2 3 | modal.close('Accepted'); console.log(modal.returnValue); // logs `Accepted` | 
他にもイベントが利用できます。closeとcancelで、closeはモーダルが閉じられた時のトリガーで、cancelはモーダルを閉じるためにescを押した時のトリガーです。
背景をクリックした時にモーダルが閉じる機能がないと思うかもしれませんが、これには回避策があります。背景をクリックすると、<dialog>をイベントターゲットとしてクリックイベントが発生します。そして子要素がモーダルのスペース全体を満たすようにモーダルを構築すると、それらの子要素がモーダル内のクリックのターゲットになります。これを利用して、モーダル上のクリックをチェックし、モーダル自体がクリックイベントのターゲットである時に閉じます。
| 1 2 3 4 5 | modal.addEventListener('click', (event) => {   if (event.target === modal) {     modal.close('cancelled');   } }); | 
この方法は完璧ではありませんが、機能します。背景でクリックを検出する方法が見つかったら、ぜひお知らせください。
<dialog>要素で実装するモーダル ボックス
下記のデモに、私は<dialog>要素の多くの機能を盛り込みました。<dialog>で何ができるのか、確認してみてください。
ポリフィルを含んでいるので、IE9+で動作します。
See the Pen <dialog&rt; by Keith J. Grant (@keithjgrant) on CodePen.
sponsors















