dialogタグの使い方(領域展開)・HTMLとJavaScriptで簡単なDialog・モーダルを作成する方法

dialog_tag

こんにちはフロントエンドエンジニアのまさにょんです!

今回は、dialogタグの使い方(領域展開)・HTMLとJavaScriptで簡単なDialog・モーダルを作成する方法について解説していきます。

dialogタグの使い方・簡単なDialog・モーダルを作成する方法

今回の記事は、Dialogタグの使い方をしっかり理解モーダルを作成してみよう を参考・引用させていただき学習した内容をまとめた記事になります。

REFFECTさん、いつも素晴らしい記事をありがとうございます。

それでは、本題のdialogタグ の使い方・簡単なDialog・モーダルを作成する方法について解説していきます。

dialogタグのブラウザ対応状況

まず、一番重要な各ブラウザのdialogタグの対応状況は次のとおりです。

各ブラウザで、対応済みなので、問題なく使用できることで一安心です。

[ 引用: MDN dialog要素 ]

dialogの使い方と特徴

dialogタグを使用する上で押さえておきたい使い方と特徴は、次のとおりです。

  1. dialog要素にはopen属性をつけない場合は何も表示されないです。
    • 実態は、open属性の有無によるdisplay属性のnoneblockかのSwitchになります。
    • つまり、dialog要素にopen属性を追加することで、Dialogが表示されるので、動的なopen属性の追加が必要になります。
  2. HTMLDialogElement.show()またはHTMLDialogElement.showModal()を使用することで、open属性を追加して、Dialogを表示することができます。
    • HTMLDialogElement.show()は、open属性を追加するだけのメソッドです。
    • HTMLDialogElement.showModal()は、open属性の他にtop-layerbackdropの属性も追加するメソッドです。
      • top-layerは、z-index を設定しなくても一番上の Layer として表示される属性です。
      • backdropは、Dialogの背景色を設定するための属性です。
  3. HTMLDialogElement.close() を使用することで、open属性を削除して、Dialogを非表示にすることができます。

それでは、上記の特徴を理解した上で、SampleCodeとその実行結果を見ていきます。

dialogタグで作るDialogのSampleCodeと実行結果

今回のDialogのSampleCodeを実行すると、初期画面は、次のような Openボタンが表示されているだけです。

そして、これをClickすると、次のような Dialogが中央に表示されます。

上記のSampleCodeは、次のとおりです。

要点には、Numberと解説を掲載しています。

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Dialog-Test</title>
  </head>
  <style>
    /* 
      1. 背景のスクロールの停止
      => ページ内のコンテンツが多くスクロールが可能なページで、Dialog を表示すると、 
      => Dialog が中央に表示されていても背景のスクロールを行うことができます。
      => Dialog が表示された状態で背景のスクロールを停止するために 次のようなStyleを追加します。
    */
    html:has(dialogアコーディオンにtitleを入力してください) {
      overflow: hidden;
    }
    /* 2. dialog の背景は backdrop で設定されているので backdrop に背景色を設定することで指定した色に変わります。 */
    dialog::backdrop {
      background-color: skyblue;
      /* background-color: rgb(250, 250, 250, 0.5); */
    }
    /* 3. 「padding: 0」を追加で、Dialog内部の paddingでのClick判定を無効化する */
    .custom-dialog {
      padding: 0;
      width: 500px;
      border: 1 solid black;
      border-radius: 8px;
    }
  </style>
  <body>
    <div>
      <button class="openBtn">Open</button>

      <!-- 4. dialogタグ -->
      <dialog class="custom-dialog">
        <!-- 
          5. divタグ 
          => style を設定することで dialog の領域一杯にクリック領域を調整しています 
          => dialog 要素の中に div 要素を追加することで、追加した div 要素内であればクリックしたとしても Dialog を非表示にさせないように設定を行います。
        -->
        <div style="padding: 1em">
          <h2>Dialog</h2>
          <button class="closeBtn">Close</button>
        </div>
      </dialog>

      <script>
        // 6. Dialog & openBtn & closeBtn Element
        const dialog = document.querySelector("dialog");
        const openBtn = document.querySelector(".openBtn");
        const closeBtn = document.querySelector(".closeBtn");

        openBtn.addEventListener("click", () => {
          // 7. HTMLDialogElement.showModal()
          // => open属性追加 & top-layer & backdrop の追加
          // => top-layer は z-index を設定しなくても一番上の Layer として表示されるので、
          // => Dialog が表示された場合に下の Layer にアクセスすることができせん。
          // => backdrop は背景色を設定するために利用することができます。デフォルトでは薄いグレーが設定されています。
          dialog.showModal();
        });

        closeBtn.addEventListener("click", () => {
          // 8. HTMLDialogElement.close() を使用することで、open属性を削除して、Dialogを非表示にすることができます。
          dialog.close();
        });

        dialog.addEventListener("close", (e) => {
          // 9. close イベント
          // => Dialog を非表示にする場合に close イベントを設定することで Dialog が非表示になったことを検知することができます。
          console.log("Dialog が Close されました");
        });

        /**
         * 10. Dialog の外側のクリック
         * => Dialog の外側にある背景をクリックすることで Dialog を非表示にする場合の設定を確認していきます。
         * => モーダルウィンドウでは背景をオーバーレイと呼ぶことがありますが、オーバーレイをクリックした場合に表示されている Dialog を非表示にします。
         */
        dialog.addEventListener("click", (event) => {
          console.log("Dialog_Click");
          console.log(event.target);
          // ポイント1: 外側の領域も含めた DialogElementを Clickしていたら、Closeする
          // ポイント2: dialogタグ内部の divタグより内側は、対象外にする
          if (event.target === dialog) {
            dialog.close();
          }
        });
      </script>
    </div>
  </body>
</html>

Dialogの領域展開・Dialogの外側のクリックと、内側のクリックの判定制御について

Dialog の外側のクリックと、内側のクリックの判定制御について、Logicは、SrcCodeに記載してある解説のとおりになります。

一応、ポイントをまとめると、次のとおりです。

  1. Dialogは、HTMLDialogElement.showModal()で表示しているので、top-layerに領域展開している。
    • 周りの背景部分も、Dialogの領域。
  2. dialogタグにpadding: 0を追加で、Dialog内部のpaddingでのClick判定を無効化する。
  3. dialogタグ直下のdivタグをstyle設定で、Dialog内部すべてを満たすようにする。
  4. dialogタグのclickイベントの際に、dialogタグかdialog以外かで、判定する。
    • Dialogの外側の背景部分は、top-layerで領域展開しているのでdialogタグ判定になる。
    • Dialogの内側の部分は、paddingを0で無くしているので、divタグの領域に収まり、dialog判定ではなくなる。

Dialogの内側で、Clickした場合の console結果は次のとおり。

Dialogの外側の背景部分で、Clickした場合の console結果は次のとおり。

まとめ

dialogタグは、仕組みを理解すれば、簡単にDialogを作成できることがわかったので、実務でも活用していきたいと思います。

JavaScript書籍 Ver. 中級-上級者向け

JavaScript書籍 Ver. 初級者向け

Twitterやってます!Follow Me!

神聖グンマー帝国の逆襲🔥

神聖グンマー帝国の科学は、世界一ぃぃぃぃぃぃ!!!!!

参考・引用

  1. Dialogタグの使い方をしっかり理解モーダルを作成してみよう
  2. <dialog>: ダイアログ要素

最近の投稿