ジャンルから探す

Web Design English

jQueryでモーダルウィンドウを作る|dialog要素で作る方法も

この記事では、jQueryを使ってモーダルウィンドウをさくっと作成する方法をご紹介します。

結論から書くと、HTMLのダイアログ要素 <dialog> を使えばjQueryもCSSもほぼ書かずに作れます。Escキーでの閉じる操作もフォーカスの制御も最初から備わっています。既存サイトにjQueryが入っている場合は、この記事のjQuery版が使えます。

両方の作り方を載せるので、状況に合うほうを選んでください。

スポンサーリンク

モーダルウィンドウの作成例

この記事で作成するモーダルウィンドウの作成例です。

See the Pen
jQuery-モーダルウィンドウ
by りん@エンジニア (@rinblog0408)
on CodePen.

モーダルウィンドウのHTML構造を作成する

モーダルウィンドウを表示するために、HTML内にモーダルのコンテンツを定義します。今回はjQueryを使うので、jQueryのライブラリの読み込みも記述しておきます。

<div id="myModal" class="modal">
  <div class="modal-content">
    <div>
      <p>モーダルのコンテンツをここに追加</p>
    </div>
    <button id="closeModalBtn">閉じる</button>
  </div>
</div>

<button id="openModalBtn">モーダルを開く</button>

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>

読み込むjQueryのバージョンに注意してください。3.5.0より前のjQueryにはXSSの脆弱性(CVE-2020-11022 / CVE-2020-11023)があります。公開するサイトでは3.5.1以降を読み込んでください。

スポンサーリンク

CSSスタイルの追加

モーダルウィンドウを見栄え良く表示するために、CSSスタイルを追加します。

.modal {
  display: none; /* 初期状態では非表示 */
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5); /* モーダル背景の半透明な黒 */
}

.modal-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: #fff;
  padding: 20px;
}

jQueryを使用してモーダルを表示する

以下のjQueryコードを追加すると、ボタンをクリックしたときにモーダルウィンドウが表示されます。

$(document).ready(function() {
  $("#openModalBtn").on("click", function() {
    $("#myModal").show();  // モーダルを表示
  });

  $("#closeModalBtn").on("click", function() {
    $("#myModal").hide();  // モーダルを非表示
  });
});

開閉だけでは足りない3つのこと

結論:上のコードはモーダルの見た目を作るだけで、モーダルとして必要な挙動が3つ足りていません。

▼足りない挙動

不足 起きること
Escキーで閉じられない キーボードだけの操作で閉じられない
背景をクリックしても閉じない 閉じるボタンを探すことになる
背景の要素にフォーカスが移る Tabキーでモーダルの外へ抜けてしまう

最初の2つはすぐ足せます。

$(document).ready(function() {
  const $modal = $("#myModal");

  function openModal() {
    $modal.show();
    // モーダル内の最初のボタンにフォーカスを移す
    $modal.find("button").first().trigger("focus");
  }

  function closeModal() {
    $modal.hide();
    // 開いたボタンにフォーカスを戻す
    $("#openModalBtn").trigger("focus");
  }

  $("#openModalBtn").on("click", openModal);
  $("#closeModalBtn").on("click", closeModal);

  // 背景(オーバーレイ)のクリックで閉じる
  $modal.on("click", function(e) {
    if (e.target === this) closeModal();
  });

  // Escキーで閉じる
  $(document).on("keydown", function(e) {
    if (e.key === "Escape" && $modal.is(":visible")) closeModal();
  });
});

e.target === this の判定が要ります。これが無いと、モーダルの中身をクリックしただけでも閉じてしまいます。

3つ目のフォーカスの閉じ込め(フォーカストラップ)を自前で書くのは手間がかかります。そこまで必要なら、次の <dialog> を使うほうが早いです。

スポンサーリンク

dialog要素ならJavaScriptがほぼ要らない

結論:HTMLの <dialog> 要素を使うと、Escキーでの閉じる操作、背景の暗転、フォーカスの制御が最初から付いてきます。

<dialog id="myDialog">
  <p>モーダルのコンテンツをここに追加</p>
  <form method="dialog">
    <button>閉じる</button>
  </form>
</dialog>

<button id="openDialogBtn">モーダルを開く</button>
const dialog = document.getElementById("myDialog");

document.getElementById("openDialogBtn").addEventListener("click", () => {
  dialog.showModal();
});

JavaScriptはこの3行だけです。

showModal() で開くのがポイントです。show() でも表示できますが、それだと背景が操作できてしまい、モーダルになりません。

  • showModal():背景を操作できなくする(モーダル)
  • show():背景を操作できる(モードレス)

閉じるボタンは <form method="dialog"> で囲むと、JavaScriptを書かずに閉じられます。

背景(バックドロップ)のスタイルは ::backdrop で指定します。

#myDialog {
  border: none;
  border-radius: 8px;
  padding: 20px;
}

#myDialog::backdrop {
  background-color: rgba(0, 0, 0, 0.5);
}

背景クリックで閉じたい場合だけ、数行足します。

dialog.addEventListener("click", (e) => {
  if (e.target === dialog) dialog.close();
});

<dialog> の中身は要素の内側に描かれるため、e.target が dialog 自身になるのは背景部分をクリックしたときだけです。

どちらの作り方を選ぶか

結論:新しく作るなら <dialog>、既存サイトに足すならjQuery版です。

▼2つの作り方の比較

dialog要素 CSS + jQuery
JavaScript 3行 開閉+Esc+背景クリック
Escキーで閉じる 最初から対応 自分で書く
背景の暗転 ::backdrop 自分でCSSを書く
フォーカスの閉じ込め 最初から対応 自前実装は難しい
スクロールの固定 最初から対応 自分で書く
細かい挙動の制御 しづらい 自由にできる

いちばん差が出るのはフォーカスの扱いです。自前のモーダルはTabキーで背景の要素へ抜けてしまい、キーボードだけで操作している人には「閉じられないのに触れない」状態になります。<dialog> はこれを自動で防ぎます。

要素の表示・非表示を切り替える実装は、CSSとjQueryでアコーディオンを実装するやjQueryでドロップダウンメニューを実装する5つの方法でも同じ考え方で作れます。どちらも <details> やCSSだけの代替を載せています。

クリックされた要素から対象を辿る処理でつまずいたら、jQueryで親要素を取得する方法に .closest() の使い方をまとめています。

▼HTML/CSS/JavaScriptの学習本を探してる方はこちらの記事をどうぞ