12周年記念パーティ開催! 2024/5/10(金) 19:00

HTMLでダイアログを表現する 前編 dialog要素の基本

Webページで表示されるダイアログを、HTMLで簡単に表現できるようになるdialog要素。今回は基本的な使い方からフォームとの連携、showModal()の使用を学びます。

発行

著者 坂巻 翔大郎 フロントエンド・エンジニア
HTMLでダイアログを表現する シリーズの記事一覧

はじめに

Web制作では、window.alert()window.prompt()を使用したダイアログであったり、HTMLやCSS、そしてJavaScriptを用いて表示するダイアログを頻繁に扱います。そういったダイアログをHTMLで簡単に表現できるようになるのが、dialog要素です。

HTML 5.1 Nightly W3C Editor's Draft 23 March 2015

dialog要素はHTML5.1で導入が検討されている、ページの中でダイアログ機能を使えるようにする要素です。dialog要素はJavaScriptで使用するwindow.alert()window.prompt()のようなダイアログをHTML上で表現することが可能です。また、HTML上に存在するCSSでスタイリングすることもできます。執筆の6月下旬現在では、レンダリングエンジンにBlinkを搭載しているブラウザ(Chrome・Opera)のみ、dialog要素を使用することができます。

なお本記事では、操作画面でユーザになんらかの動作を促すために表示されるウインドウのことを「ダイアログ」と呼びます。このダイアログには、表示中はダイアログ以外の操作ができなくなる「モーダルダアログ」と、ダイアログ以外のウインドウの操作ができる「モードレスダイアログ」があり、本記事では分けて表記します。

dialog要素の仕様

まず、dialog要素は、以下のように使用します。

<dialog>これはモードレスダイアログです。</dialog>

しかし、このままでは画面には何も表示されません。dialog要素が画面に表示されるためには、JavaScript APIを使って制御する必要があります。あるJavaScript APIが使われたとき、dialog要素にopen属性が付与され、初めてそのモードレスダイアログ/モーダルダイアログが画面に表示されます。

<dialog open>これはモードレスダイアログです。</dialog>

もし、予めモードレスダイアログを開いておきたい場合は、open属性を付与しておくことで表示することができます。

dialog要素のDOMインタフェース

それでは、dialog要素が持つ専用のJavaScript APIをいくつか見ていきましょう。

dialog.show()

まず非表示になっているdialog要素を表示するための、show()メソッドです。

HTMLは以下のようになっています(CSSは特に記述していません)。

<dialog>
  <p>これはモードレスダイアログです</p>
</dialog>
<button id="show">モードレスダイアログを開く</button>

次に、JavaScriptを見てみましょう。

var dialog = document.querySelector('dialog');
var btn_show = document.getElementById('show');
btn_show.addEventListener('click', function() {
  dialog.show();
}, false);

document.querySelector('dialog')で取得したdialog要素に対して、dialog.show()と、jQueryのように実行するだけで、画面の中央にdialog要素が表示されました。

このとき、DevToolsなどでdialog要素を確認すると、open属性が付与されているのがわかります。

dialog.close()

次に、表示されたdialog要素を非表示にするための、close()メソッドです。

HTMLは以下のようになっています(CSSは特に記述していません)。

<dialog>
  <p>これはモードレスダイアログです</p>
  <button id="close">モードレスダイアログを閉じる</button>
</dialog>
<button id="show">モードレスダイアログを開く</button>

次に、JavaScriptを見てみましょう。

var dialog = document.querySelector('dialog');
var btn_show = document.getElementById('show');
var btn_close = document.getElementById('close');
btn_show.addEventListener('click', function() {
  dialog.show();
}, false);
btn_close.addEventListener('click', function() {
  dialog.close();
}, false);

先ほどと同様に、dialog要素を取得し、それに対してdialog.close()とすると、dialog要素が非表示になります。

dialog.showModal()

もう一つ、dialog要素を表示するメソッドが存在します。それはshowModal()メソッドです。おそらく、これが一番期待していた機能なのかもしれません。

上記のデモの「ダイアログを開く」ボタンを押したとき、画面が少し暗くなります。そして表示している間、その背後にあるテキストを選択したりボタンを押したりすることができないこと、さらにはEscapeキーを押したときに、ダイアログが非表示になることに気づいたでしょうか。これがモーダルダイアログです。このデモでは、テキストを選択できないようにしたり、Escapeキーを押したらダイアログを閉じる、といったことをJavaScriptなどに指定しているわけではありません。

では、コードを見ていきます。まずはHTMLですが、前述のものから変更はしていません。

<dialog>
  <p>これはモーダルダイアログです</p>
  <button id="close">モーダルダイアログを閉じる</button>
</dialog>
<button id="show">モーダルダイアログを開く</button>

次に、JavaScriptを見てみましょう。

var dialog = document.querySelector('dialog');
var btn_show = document.getElementById('show');
var btn_close = document.getElementById('close');
btn_show.addEventListener('click', function() {
  dialog.showModal();
}, false);
btn_close.addEventListener('click', function() {
  dialog.close();
}, false);

JavaScriptの部分もshowと書いていた部分をshowModalに変更しました。たったこれだけです。たったこれだけで、テキストが選択できないようになったり、Escapeキーでモーダルダイアログを非表示にすることができます。

モーダルダイアログが閉じたときのイベント

次のデモでは、モーダルダイアログが閉じたときにはcloseイベントが発生し、Escapeキーを押したときにはcancelイベントが発生します。

デモ上でモーダルダイアログを開いて、ボタンを押して閉じたときと、Escapeキーを押して閉じたときに、コンソールにメッセージが表示されます。

var dialog = document.querySelector('dialog');
var btn_show = document.getElementById('show');
var btn_close = document.getElementById('close');
btn_show.addEventListener('click', function() {
  dialog.showModal();
}, false);
btn_close.addEventListener('click', function() {
  dialog.close();
}, false);
dialog.addEventListener('close', function(event){
  console.log('close', event);
});
dialog.addEventListener('cancel', function(event){
  console.log('cancel', event);
});

また、Escapeキーを押したときに、モーダルダイアログが閉じてほしくない場合は、以下のようにキャンセルします。

dialog.addEventListener('cancel', function(event){
  event.preventDefault();
  console.log('cancel', event);
});

デモで見てみましょう。デモでは、Escapeキーを押したときに、cancelイベントは実行されコンソールにメッセージが表示されていますが、モーダルダイアログは閉じていません。

dialog.returnValue

window.prompt()のように、開かれたモーダルダイアログ内の入力要素にユーザが何かしらを入力し、モーダルダイアログを閉じるような場合、その入力された値をdialog.close()の引数に渡すと、dialog.returnValueプロパティにその値がセットされます。

HTMLは以下のようになっています。モーダルダイアログ内に入力要素を追加しました。

<dialog>
  <p>これはモーダルダイアログです</p>
  <div>
    <input type="text" id="input_value" value="" placeholder="何かしら入力してください">
  </div>
  <div>
    <button id="close">閉じて、入力した内容をalertする</button>
  </div>
</dialog>
<button id="show">モーダルダイアログを開く</button>

次に、JavaScriptの部分です。

var dialog = document.querySelector('dialog');
var btn_show = document.getElementById('show');
var btn_close = document.getElementById('close');
btn_show.addEventListener('click', function() {
  dialog.showModal();
}, false);
btn_close.addEventListener('click', function() {
  var value = document.getElementById('input_value').value;
  dialog.close(value);
}, false);
dialog.addEventListener('close', function(event){
  alert(this.returnValue);
});

#closeがクリックされたときに、#input_valueのvalueの値を取得します。そしてモーダルダイアログを閉じるclose()メソッドを呼ぶ際に、そのvalueの値を引数として渡しています。さらに、モーダルダイアログを閉じたときのcloseイベントの中で、thisつまりそのdialog要素自身のreturnValueに、先ほどのvalueの値がセットされているので、確認をするためにアラートを表示しています。

form要素との連携

dialog要素の中に、form要素を配置し、そのform要素のmethod属性値にdialogを指定すると、フォームとモーダルダイアログを連携させることができます。

具体的な動作としては、そのフォームが送信されたとき、モーダルダイアログが閉じられます。さらに、送信の際に使用されたtype属性値がsubmitであるボタンの値がdialog.returnValueにセットされます。

HTMLは以下のようにしています。ここではモーダルダイアログを開いた際に、「いいえ」にフォーカスさせたいのでautofocus属性を使用しました。autofocus属性を使うことで、モーダルダイアログが開かれたとき、その属性があるフォームコントロール要素に自動的にフォーカスを当てることができます。

<dialog>
  <form method="dialog">
    <p>これはモーダルダイアログです。本当によろしいですか?</p>
    <button type="submit" value="yes">はい</button>
    <button type="submit" value="no" autofocus>いいえ</button>
  </form>
</dialog>
<button id="show">モーダルダイアログを開く</button>

一つ前のデモでは、閉じるボタンを用意し、そのボタンが押されたときに、入力要素のvalueの値を取得しましたが、form要素と連携する場合は非常にシンプルです。

var dialog = document.querySelector('dialog');
var btn_show = document.getElementById('show');
btn_show.addEventListener('click', function() {
  dialog.showModal();
}, false);
dialog.addEventListener('cancel', function(event){
  event.preventDefault();
});
dialog.addEventListener('close', function(event){
  if (this.returnValue === 'yes') {
    alert('はい をクリックしました。');
  } else {
    alert('いいえ をクリックしました。');
  }
});

button[type="submit"]が押されたとき、自動でdialog要素のreturnValueに、押したボタンのvalue属性値がセットされます。そして、dialog要素が閉じた際に発生するcloseイベントの中で、その値を確認し、値に応じたアラートを表示しています。

dialog要素でしかできないこと

ここまでが、基本的なdialog要素の使い方でした。最後に、dialog要素でしかできないことを見てみましょう。

z-index: 2147483647;(最大値)で、かつ</body>の直前に配置した「最前面に来るであろう要素」とdialog要素を並べてみました。

*注:z-indexについて

z-indexプロパティは要素の重なり順を指定でき、原則として値が大きい要素ほど前面にきます。z-indexプロパティについてはCodeGridでも、記事になっています。

HTMLは以下のようになっています。

<body>
  <dialog>
    <p>これはモーダルダイアログです。本当によろしいですか?</p>
  </dialog>
  <button id="show">モーダルダイアログを開く</button>
  <div class="highZindex">The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.</div>
</body>

次に、CSSでは、dialog要素のz-indexを1にし、最前面に来るであろう.highZindexz-indexには最大値を指定しています。z-indexの値だけから考えると、.highZindexが最前面に来るはずです。

dialog {
  position: absolute;
  z-index: 1;
}
.highZindex {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  margin: auto;
  width: 300px;
  height: 300px;
  z-index: 2147483647;
  background-color: tomato;
}

それでは、デモを見てみましょう。

「モーダルダイアログを開く」を押したときに、モーダルダイアログが最前面に表示されています。dialog要素がshowModal()を使って表示されたときのモーダルダイアログは、z-indexの値にかからわず、すべての要素の上に表示されるトップレイヤーという箇所に配置されます。dialog要素があれば、z-indexやスタック文脈を気にすることなく、画面の最前面にモーダルダイアログを表示することが可能になります。

まとめ

今回は、dialog要素の基本的な使い方とフォームとの連携、そしてshowModal()を使用したモーダルダイアログは、必ず画面の最前面に来るということを学びました。

ここまで、まったく触れていませんが、dialog要素が表示されたときの見た目や、表示方法はとても簡素なものです。次回はその見た目のカスタマイズと、モーダルダイアログが現れるとき、消えるときにアニメーションを付けるといったカスタマイズを紹介する予定です。