2026年8月27日
2026年8月27日
WordPressでモーダルダイアログを実装する方法|dialog要素と子テーマで作る
モーダルダイアログは、ページの上に重ねて表示し、閉じるまで背景を操作できなくする UI です。お知らせ、画像の詳細、確認メッセージなどに使えます。
以前は div を display: none で隠しておき、JavaScript で表示を切り替える作り方が一般的でした。しかしその方法では、Esc キーで閉じる、キーボードのフォーカスをダイアログの中に留める、背景をスクリーンリーダーから隠す、といった処理をすべて自分で書く必要があります。現在は HTML の <dialog> 要素を使えば、これらをブラウザーが受け持ちます。<dialog> は 2022年3月から主要ブラウザーで広く使える状態(Baseline)になっています。
この記事では、WordPress の子テーマに CSS と JavaScript を追加し、ブロックエディターの「カスタム HTML」ブロックにダイアログを置く方法を説明します(2026年10月時点の WordPress 6.9 で確認した内容です)。
dialog 要素の基本
<dialog> には開き方が 2 つあります。
| 開き方 | 動作 |
|---|---|
dialog.showModal() |
モーダルとして開く。ダイアログの外側は操作できなくなり(inert)、Esc キーで閉じられる。背景は ::backdrop で装飾できる |
dialog.show() |
モーダルでない形で開く。背景も操作でき、Esc キーでは閉じない |
この記事ではモーダルにしたいので showModal() を使います。閉じるには次の方法があります。
- JavaScript で
dialog.close()を呼ぶ - ダイアログ内の
<form method="dialog">を送信する(サーバーには送信されず、ダイアログが閉じる) - モーダルとして開いている場合は Esc キー
showModal() で開くと、フォーカスはダイアログ内の最初のフォーカスできる要素に移ります。特定の要素にフォーカスさせたい場合は、その要素に autofocus 属性を付けます。
作るもの
- ボタンを押すとダイアログが開く
- 「閉じる」ボタン、Esc キー、背景のクリックで閉じる
- 開いている間はページ本体がスクロールしない
- 1 ページに複数のダイアログを置ける
ファイル構成は次のとおりです(子テーマのフォルダー名は例です)。
wp-content/themes/my-child-theme/
├── functions.php
└── assets/
├── modal.css
└── modal.js
テーマのファイルを直接編集すると、テーマの更新で上書きされて消えます。子テーマが無い場合は先に作成してください。手順は「WordPressで子テーマを作成する方法」で説明しています。
手順
1. CSS を作る
assets/modal.css を作成します。
/* ダイアログ本体。余白は内側の要素に付ける(理由は手順3) */
.my-modal {
padding: 0;
border: none;
border-radius: 8px;
width: min(90vw, 560px);
max-height: 85vh;
box-shadow: 0 10px 30px rgb(0 0 0 / 0.3);
}
.my-modal__body {
padding: 24px;
}
/* 背景の暗い幕 */
.my-modal::backdrop {
background: rgb(0 0 0 / 0.5);
}
.my-modal__close {
margin-top: 16px;
cursor: pointer;
}
/* 開いている間はページ本体をスクロールさせない */
body:has(dialog.my-modal[open]) {
overflow: hidden;
}
/* 開くときの軽いアニメーション */
.my-modal[open] {
animation: my-modal-in 0.2s ease-out;
}
@keyframes my-modal-in {
from {
opacity: 0;
transform: translateY(8px);
}
to {
opacity: 1;
transform: none;
}
}
/* 動きを減らす設定の利用者にはアニメーションしない */
@media (prefers-reduced-motion: reduce) {
.my-modal[open] {
animation: none;
}
}
モーダルとして開いた <dialog> は、ブラウザーの標準スタイルで画面の中央に配置されます。位置を指定する CSS は不要です。
2. JavaScript を作る
assets/modal.js を作成します。ページ全体のクリックを 1 か所で受け取る書き方にしているので、ダイアログやボタンが何個あっても同じコードで動きます。
document.addEventListener('click', function (event) {
// data-modal-open="ダイアログのid" を持つボタンで開く
const opener = event.target.closest('[data-modal-open]');
if (opener) {
const dialog = document.getElementById(opener.dataset.modalOpen);
if (dialog && typeof dialog.showModal === 'function') {
dialog.showModal();
}
return;
}
// 背景(::backdrop)のクリックは dialog 要素自身へのクリックとして届く
if (event.target instanceof HTMLDialogElement && event.target.open) {
event.target.close();
}
});
3. 背景クリックで閉じる仕組み
::backdrop は <dialog> 要素の一部として扱われるため、背景をクリックすると event.target が <dialog> 自身になります。一方、ダイアログの中身をクリックしたときは、内側の要素(.my-modal__body やその子)が event.target になります。
手順1の CSS で <dialog> の padding を 0 にし、余白を内側の .my-modal__body に付けたのはこのためです。<dialog> 自体に余白があると、余白部分のクリックも「背景のクリック」と判定され、ダイアログが閉じてしまいます。
背景クリックで閉じたくない場合(入力フォームなど、誤って閉じると困るもの)は、2 つ目の if ブロックを削除してください。Esc キーと「閉じる」ボタンでは閉じられます。
4. functions.php で読み込む
子テーマの functions.php に追加します。WordPress 6.3 以降は、wp_enqueue_script() の 5 番目の引数に配列を渡して defer を指定できます。
<?php
// 子テーマの functions.php に追加する
add_action( 'wp_enqueue_scripts', function () {
$dir = get_stylesheet_directory();
$uri = get_stylesheet_directory_uri();
wp_enqueue_style(
'my-modal',
$uri . '/assets/modal.css',
array(),
filemtime( $dir . '/assets/modal.css' )
);
wp_enqueue_script(
'my-modal',
$uri . '/assets/modal.js',
array(),
filemtime( $dir . '/assets/modal.js' ),
array(
'strategy' => 'defer',
'in_footer' => true,
)
);
} );
すでに functions.php の先頭に <?php がある場合は、2 行目以降だけを追加します。バージョンにファイルの更新日時(filemtime())を使っているので、CSS や JavaScript を編集するとブラウザーのキャッシュが自動で切り替わります。
特定のページだけで読み込みたい場合は、関数の最初に条件を足します。
<?php
add_action( 'wp_enqueue_scripts', function () {
// 固定ページ「contact」以外では読み込まない
if ( ! is_page( 'contact' ) ) {
return;
}
// ...手順4の wp_enqueue_style / wp_enqueue_script をここに書く...
} );
wp_enqueue_scripts の引数の詳細は「wp_enqueue_scriptsでJSとCSSを読み込む方法」を参照してください。
5. ダイアログの HTML を置く
ダイアログを表示したい投稿や固定ページを編集し、「カスタム HTML」ブロックを追加して次の HTML を貼り付けます。
<button type="button" class="wp-element-button" data-modal-open="info-modal">詳しく見る</button>
<dialog id="info-modal" class="my-modal" aria-labelledby="info-modal-title">
<div class="my-modal__body">
<h2 id="info-modal-title">お知らせ</h2>
<p>ここに表示したい内容を書きます。</p>
<form method="dialog">
<button type="submit" class="my-modal__close">閉じる</button>
</form>
</div>
</dialog>
- ボタンの
data-modal-openの値と、<dialog>のidを一致させます。 - 同じページに複数置く場合は、
id(とaria-labelledby・見出しのid)をダイアログごとに別の値にします。 wp-element-buttonは、ブロックテーマのボタンのスタイルを当てるためのクラスです。不要なら外してかまいません。aria-labelledbyで見出しを指定すると、スクリーンリーダーがダイアログの名前として読み上げます。<dialog>要素自体にはtabindexを付けないでください。
WordPress は、投稿に保存する HTML を利用者の権限で絞り込みます。単一サイトの管理者と編集者は unfiltered_html 権限を持つため、そのまま保存されます。投稿者などそれ以外の権限で保存すると、一部のタグや属性が取り除かれることがあります。
6. 動作を確かめる
公開したページで次の点を確認します。
- ボタンを押すとダイアログが開き、背景が暗くなる
- 「閉じる」ボタン、Esc キー、背景のクリックで閉じる
- 開いている間、Tab キーでダイアログの外にフォーカスが出ない
- ダイアログの中身(文字や余白)をクリックしても閉じない
- スマートフォンの幅でも画面からはみ出さない
開かない場合は、ブラウザーの開発者ツール(F12)の「Console」でエラーを、「Network」で modal.js と modal.css が読み込まれているか(404 になっていないか)を確認します。キャッシュ系プラグインを使っている場合は、キャッシュを削除してから確認してください。
注意点
- ページを開いた直後に自動で表示しない: 読み込みと同時に本文を覆うダイアログは、読者の邪魔になりやすい表示です。この記事のように、読者がボタンを押したときに開く使い方が基本です。
- 閉じる手段を見える形で用意する: Esc キーを使えない利用者もいるため、画面に「閉じる」ボタンを置きます。
- フォームを入れる場合: ダイアログ内のフォームから情報を送る場合、サーバー側での入力値の検証やエスケープは通常のフォームと同じく必要です。お問い合わせフォームなどはフォーム用のプラグインで作り、そのショートコードを含むブロックをダイアログの中に置く方法もあります。
- ポップアップ用プラグインとの違い: 表示のタイミング(スクロール量・離脱時)や表示回数の制御が必要なら、専用のプラグインを使うほうが早いことがあります。比較は「WordPressでポップアップを実装する方法」を参照してください。
まとめ
- モーダルダイアログは HTML の
<dialog>とshowModal()で作ると、Esc キーでの終了や背景の操作無効化をブラウザーが受け持ちます。 - CSS と JavaScript は子テーマに置き、
functions.phpのwp_enqueue_scriptsで読み込みます。 - ダイアログの HTML は「カスタム HTML」ブロックに置き、ボタンの
data-modal-openとidを一致させます。 - 背景クリックで閉じる処理は、
<dialog>のpaddingを 0 にして中身を内側の要素で包むと誤判定しません。