dialog要素で遊んでみた

HTMLの新しめの要素について調べていたら、
HTML5.2から入った`dialog`要素が出てきたので、遊んでみました！（2017年にW3C勧告された要素です）


## 対応ブラウザ確認

Can I use でdialogがどのブラウザに対応しているか見てみます。
![Can I use.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1030413/c178bea5-7847-9992-8b20-15afeebedce4.png)
https://caniuse.com/?search=dialog

IEはさておき、Firefox、Safariではまだ対応していないようで、Webサイトへの普及はこれからなのかなと思いました。どうりでお見かけしないわけだ！

ちなみに、VSコードでhtmlファイル作って`p`とか打つと勝手に`<p></p>`と変換してくれるのですが、`dialog`と打っても変換されませんでした。これは自力で打っていくしかないですね。

## ::backdrop擬似要素が使える
全画面モードに配置される要素と`dialog`要素の両方に使えて、それらの直下に置かれる擬似要素です。
`dialog`要素だったら要素の下をぼかしたり隠したりするのに用います。
PCではSafari以外は使える擬似要素です。


## 実装
やってみました

```html
<dialog>
  <p>あいうえお</p>
</dialog>
```

結果は

![dialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1030413/ce1365ab-0c06-0635-fedd-1bcbfccb7743.png)


真っ白。
しかし、`dialog`要素に`open`属性をつけると、

```html
<dialog open>
  <p>あいうえお</p>
</dialog>
```

![dialog-open.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1030413/27db017b-662f-dfbd-85e4-49fa89fb37e7.png)


表示されます。`open`属性のつけ外しでダイアログの表示・非表示ができることがわかります。
HTMLDialogElementインターフェースのメソッドで`dialog`要素を操作できるので、JSでダイアログの開閉をしてみます。ちなみに、IEとSafariでは効かないインターフェースです。


# JSでダイアログを開いてみる
新しく作成したOPEN Modalボタンを押すと、ダイアログが表示されるように実装しました。
HTML▼

```html
<dialog id="dialog">
  <p>あいうえお</p>
</dialog>

<button id="openModal">OPEN Modal</button>
```

JS▼

```html
<script>
(function() {
  var dialog = document.getElementById('dialog');
  var openModal = document.getElementById('openModal');
  openModal.addEventListener('click', function() {
    dialog.showModal();
  })
})();
</script>
```

![dialog-open-js.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1030413/f9938c62-27d3-0781-d989-9f928be8ba35.png)

実際の挙動はこちら

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="miika-codepen" data-slug-hash="YzGgrrv" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="dialog element">
  <span>See the Pen <a href="https://codepen.io/miika-codepen/pen/YzGgrrv">
  dialog element</a> by miika (<a href="https://codepen.io/miika-codepen">@miika-codepen</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

レイヤーとかどうなっているのかと思って、検証ツールで見てみると、ダイアログとレイヤーに値する部分が、それぞれ同じ`dialog#dialog`要素と表示されましたが、それぞれ別のRoleでした（ACCESSIBILITYって書いてあるところ）。一つはdialog、もう一つはgenericです。レイヤーに値する要素（Roleがgeneric）の方は、`::backdrop`擬似要素に値しそうですが、`::backdrop`擬似要素はどの要素からも継承しないためか、検証ツールで`dialog#dialog::backdrop`と表示されず、`dialog#dialog`と表示された模様です。


ダイアログに値する要素▼
![dialog-role-dialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1030413/976161bc-234c-6df8-354f-678e4e9dfa93.png)

レイヤーに値する要素▼
![dialog-role-generic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1030413/d3a87e27-0c24-2716-342d-f1b5491805ad.png)

これらのRoleは`role`属性でHTMLに設定したものではないので、JSで取得できず、よくある「ダイアログ以外をクリックしたらクローズ」の実装、つまり、「`dialog#dialog`要素以外を選択したらダイアログを閉じる」ができなかったです。
JSでの操作はできなかったですが、CSSで`dialog#dialog::backdrop`の`background`を変えることは可能です。背景色とか変えられます。

jQueryの場合は、`show()`と`hide()`で実現できます。先述した、HTMLDialogElementインターフェースは、IEとSafariで効かないのを考えると、jQueryで実装するのも手ですね。

# まとめ
`dialog`要素は`open`属性の取り外しで見え隠れする簡易なもので、`::backdrop`擬似要素のおかげでレイヤーをこちらで考えてレイヤー用のDOMを作らなくていいことがよかったです。
実装自体はしやすいし、HTMLで構造文書を目指してコーディングしていく分にはぜひ使っていきたい気持ちの一方、ブラウザの対応がまちまちなのと、ダイアログ以外をクリック・タッチしたら消える実装に道が見えないことが難でした！今後ブラウザへの対応が進むのか、`dialog`要素・`::backdrop`擬似要素が進化するのか、どうなるのか想像を膨らませて、終わりとします！


# 参考
HTML 5.2 W3C Recommendation, 14 December 2017
https://www.w3.org/TR/html52/

MDN Web Docs `<dialog>`: ダイアログ要素
https://developer.mozilla.org/ja/docs/Web/HTML/Element/dialog

MDN Web Docs ::backdrop
https://developer.mozilla.org/ja/docs/Web/CSS/::backdrop

MDN Web Docs HTMLDialogElement
https://developer.mozilla.org/ja/docs/Web/API/HTMLDialogElement