dialog要素の show(), showModal(), Popover API を比較してみた

HTMLでダイアログ (ポップアップウインドウ) が実装できる dialog 要素ですが、開くには JavaScript の show() メソッドと showModal() メソッド、そして新たに追加された Popover API を使用する方法があります。

show() メソッド、showModal() メソッド、Popover API それぞれに違いがあるので、今回はそれらを比較してみました。

show() メソッド

<p>
  <button type="button" onclick="document.getElementById('dialog').show();">
    Open
  </button>
</p>
<dialog id="dialog">
  <p>
    <button type="button" onclick="document.getElementById('dialog').close();">
      Close
    </button>
  </p>
</dialog>

show() メソッドは非モーダルダイアログを開く際に使用します。dialog 要素を開くと open 属性が追加されます。

モーダルとは、一部の機能を制限した状態を意味します。

非モーダルダイアログの場合、ダイアログ外の操作を制限しないため、ダイアログ外にあるリンクなどをクリックすることができます。

ダイアログ外をクリックしてもダイアログは閉じず、Escキー (エスケープキー) で閉じることもできません。

ブラウザのデフォルトスタイルには、position: absolute; が設定されており、ダイアログを表示した状態でスクロールしても追従しません。

showModal() メソッド

<p>
  <button type="button" onclick="document.getElementById('dialog').showModal();">
    Open
  </button>
</p>
<dialog id="dialog">
  <p>
    <button type="button" onclick="document.getElementById('dialog').close();">
      Close
    </button>
  </p>
</dialog>

showModal() メソッドはモーダルダイアログを開く際に使用します。dialog 要素を開くと open 属性が追加されます。

モーダルダイアログは、ダイアログ外の操作を制限するため、ダイアログ外にあるリンクなどはクリックすることができませんが、スクロールはできます。

ダイアログ外をクリックしてもダイアログは閉じませんが、Escキー で閉じることができます。

ブラウザのデフォルトスタイルには、position: fixed; が設定されており、ダイアログを表示した状態でスクロールすると追従します。また、::backdrop 擬似要素も設定されているため、操作できないダイアログ外を暗めに表示します。

Popover API

<p>
  <button type="button" popovertarget="dialog" popovertargetaction="show">
    Open
  </button>
</p>
<dialog id="dialog" popover="auto">
  <p>
    <button type="button" popovertarget="dialog" popovertargetaction="hide">
      Close
    </button>
  </p>
</dialog>

Popover API はダイアログを非モーダルなポップオーバーコンテンツとして開く際に使用します。dialog 要素を開いても open 属性は追加されません。開いた状態をスタイリングするには :popover-open 擬似クラスを使用します。

非モーダルなため、ダイアログ外の操作を制限しませんが、ダイアログ外をクリックするとダイアログは閉じます。Escキー でも閉じることができます。

ブラウザのデフォルトスタイルには、position: fixed; が設定されており、ダイアログを表示した状態でスクロールすると追従します。

::backdrop 擬似要素はデフォルトスタイルとしては設定されていませんが、設定することは可能です。

まとめ

show() メソッドshowModal() メソッドPopover API
モーダルかどうか非モーダルモーダル非モーダル
ボタン以外で閉じるか閉じないEscキー で閉じるEscキー とダイアログ外のクリックで閉じる
open 属性追加される追加される追加されない
position プロパティabsolutefixedfixed
::backdrop 擬似要素設定できない設定できる設定できる
dialog 要素における show(), showModal(), Popover API の比較

スタイルの違いを可能な限り近づけるためのCSS

show() メソッド, showModal() メソッド, Popover API それぞれに違いがあり、dialog 要素を使う場面に応じて適切に選択する必要があるかと思いますが、一方で、表示方法にある程度の統一感を持たせたい場合もあるかと思います。

そんなときには次の CSS コードを参考にしてみてください。pointer-events プロパティや touch-action プロパティを使用すると show() メソッドに showModal() メソッドと近い操作感を与えることもできます。

dialog {
  & {
    /* ::backdrop 擬似要素の代替 */
    border-image: linear-gradient(color-mix(in srgb, transparent, CanvasText 20%) 0% 100%) 10000 / 10000px / 10000px;

    /* position プロパティの値を fixed に統一 */
    margin: auto;
    position: fixed;
      inset: 0;

    /* padding プロパティの値を統一 */
    padding: 1rem;

    /* html 要素に設定する pointer-events: none; を上書き */
    pointer-events: auto;
  }
  &::backdrop {
    /* border-image プロパティとの重複を回避 */
    background: none;
  }

  /* ダイアログ表示時の設定 */
  html:has(&[open], &:popover-open) {
    /* スクロール不可 */
    overflow: hidden;

    /* ポインターによる操作を抑制 */
    pointer-events: none;

    /* スクロールバー非表示による幅の変化を抑制 */
    scrollbar-gutter: stable;

    /* タッチによる操作を抑制 */
    touch-action: none;
  }
}

CodePen

See the Pen dialog element by nov (@numerofive) on CodePen.

この記事の内容に関して分からないことなどがあれば、気軽にコメントしてください。それではメリクリ。

関連記事