自分だけのブログを始めませんか?
WordPressブログなら、あなたのコーディング知識でデザインのカスタマイズが自由自在。
ブログデビューに最適な初心者向けサーバー環境を徹底比較しました。

WordPressブログなら、あなたのコーディング知識でデザインのカスタマイズが自由自在。
ブログデビューに最適な初心者向けサーバー環境を徹底比較しました。
HTMLの<dialog>タグを使えば、外部ライブラリに頼ることなく、ブラウザ標準機能だけでモーダルウィンドウを実装できます。
本記事では、基本の開閉処理、CSSによるカスタマイズ、スクロール制御やアクセシビリティ対応まで実務で役立つ実装手法を解説します。
ポップアップ・モーダルウィンドウのデザインコードが欲しい人は「【html&css】画面中央表示!ポップアップ・モーダルウィンドウデザイン2選」を一読ください。
dialogとは、ブラウザがネイティブに提供するダイアログウィンドウを作成する専用タグです。
ここでは、dialogタグの使い方、専用のJavaScriptメソッドを利用したUIコンポーネントの設計、モーダルと非モーダルの違いを解説します。
dialogタグの役割showとshowModalの違い<dialog>タグは、ポップアップやアラート、入力フォームなど、ユーザーの注意を引きたいサブウィンドウを構築する役割を担います。
⭕️ HTMLにタグを置くだけでポップアップの「箱」が完成
これはdialogタグで作られたウィンドウです。
<div class="hdlg-sec1-wrapper">
<div class="hdlg-sec1-demo-area">
<div class="hdlg-sec1-box">
<div class="hdlg-sec1-label">📦 dialogタグの基本構造</div>
<div class="hdlg-sec1-visual">
<p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ HTMLにタグを置くだけでポップアップの「箱」が完成</p>
<div class="hdlg-sec1-mock-bg">
<div class="hdlg-sec1-mock-dialog">
<div style="margin:0 0 10px 0;">お知らせ</div>
<p style="font-size:12px; margin:0 0 15px 0;">これはdialogタグで作られたウィンドウです。</p>
<button class="hdlg-sec1-btn">閉じる</button>
</div>
</div>
</div>
<div class="hdlg-sec1-code">
<!-- 💡 1. ダイアログの「箱」を作る --><br>
<span class="hdlg-sec1-hl-blue"><dialog id="myDialog"></span><br>
<h2>お知らせ</h2><br>
<p>これはdialogタグで作られたウィンドウです。</p><br>
<span class="hdlg-sec1-hl-comment"><!-- 閉じるためのボタン --></span><br>
<button id="closeBtn">閉じる</button><br>
<span class="hdlg-sec1-hl-blue"></dialog></span><br><br>
/* 💡 2. JSでAPI(メソッド)を呼び出して操作する */<br>
<span class="hdlg-sec1-hl-blue">const</span> dialog = document.getElementById(<span class="hdlg-sec1-hl-green">'myDialog'</span>);<br>
<span class="hdlg-sec1-hl-comment">// 開く処理(詳細は次の見出しで解説)</span><br>
dialog.<span class="hdlg-sec1-hl-red">showModal()</span>;<br>
<span class="hdlg-sec1-hl-comment">// 閉じる処理</span><br>
dialog.<span class="hdlg-sec1-hl-red">close()</span>;
</div>
</div>
</div>
</div>.hdlg-sec1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-sec1-demo-area {
display: flex;
justify-content: center;
}
.hdlg-sec1-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-sec1-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-sec1-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
}
.hdlg-sec1-mock-bg {
background-color: rgba(0, 0, 0, 0.5);
padding: 30px;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
}
.hdlg-sec1-mock-dialog {
background-color: #fff;
padding: 20px;
border-radius: 6px;
box-shadow: 0 4px 10px rgba(0,0,0,0.2);
min-width: 200px;
}
.hdlg-sec1-btn {
background-color: #e9ecef;
border: 1px solid #ced4da;
padding: 5px 15px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-sec1-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #0d6efd;
}
.hdlg-sec1-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-sec1-hl-blue {
color: #61afef;
font-weight: bold;
}
.hdlg-sec1-hl-red {
color: #e06c75;
font-weight: bold;
}
.hdlg-sec1-hl-comment {
color: #6c757d;
font-style: italic;
}<dialog>タグを使いこなす上で重要なのが、ダイアログを開く2つのJavaScriptメソッドの違いを正しく理解することです。
show()メソッドshowModal()メソッド::backdrop疑似要素を提供し、ESCキーで閉じる機能も装備されます。ボタンを押して違いを確かめてください
※ダイアログ表示中、この文字を選択できるか試してください。
<div class="hdlg-sec2-wrapper">
<div class="hdlg-sec2-demo-area">
<div class="hdlg-sec2-box">
<div class="hdlg-sec2-label">⚖️ show() と showModal() の違い</div>
<div class="hdlg-sec2-visual">
<p style="font-size:12px; font-weight:bold; margin:0 0 10px 0;">ボタンを押して違いを確かめてください</p>
<div style="display:flex; gap:10px; margin-bottom:15px;">
<button id="btnShow" class="hdlg-sec2-btn-show">show() で開く</button>
<button id="btnShowModal" class="hdlg-sec2-btn-modal">showModal() で開く</button>
</div>
<p style="font-size:11px; color:#666; margin:0;">※ダイアログ表示中、この文字を選択できるか試してください。</p>
<dialog id="dialogShow" class="hdlg-sec2-dialog">
<div style="margin:0 0 10px 0; color:#0d6efd;">非モーダル(show)</div>
<p style="font-size:12px;">背景は暗くならず、後ろの操作も可能です。</p>
<button id="btnCloseShow" class="hdlg-sec2-btn">閉じる</button>
</dialog>
<dialog id="dialogShowModal" class="hdlg-sec2-dialog">
<div style="margin:0 0 10px 0; color:#dc3545;">モーダル(showModal)</div>
<p style="font-size:12px;">背景が暗くなり、後ろの操作はブロックされます。<br>※ESCキーでも閉じられます。</p>
<button id="btnCloseModal" class="hdlg-sec2-btn">閉じる</button>
</dialog>
</div>
<div class="hdlg-sec2-code">
<span class="hdlg-sec2-hl-comment">/* ❌ 悪い例:背景を自作しようとしている */</span><br>
dialog.<span class="hdlg-sec2-hl-red">show()</span>;<br>
document.getElementById('overlay').style.display = 'block';<br><br>
<span class="hdlg-sec2-hl-comment">/* ⭕️ 正解:showModalを使えばブラウザが全部やってくれる */</span><br>
dialog.<span class="hdlg-sec2-hl-green">showModal()</span>;<br><br>
<span class="hdlg-sec2-hl-comment">/* 背景(バックドロップ)の色を変えたい場合のCSS */</span><br>
<span class="hdlg-sec2-hl-blue">dialog::backdrop</span> {<br>
<span class="hdlg-sec2-hl-green">background-color: rgba(0, 0, 0, 0.8);</span><br>
}
</div>
</div>
</div>
</div>.hdlg-sec2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-sec2-demo-area {
display: flex;
justify-content: center;
}
.hdlg-sec2-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-sec2-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-sec2-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
}
.hdlg-sec2-btn-show {
background-color: #0d6efd;
color: #fff;
border: none;
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-sec2-btn-modal {
background-color: #dc3545;
color: #fff;
border: none;
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-sec2-btn {
background-color: #e9ecef;
border: 1px solid #ced4da;
padding: 5px 15px;
border-radius: 4px;
cursor: pointer;
margin-top: 10px;
}
.hdlg-sec2-dialog {
border: none;
border-radius: 8px;
padding: 20px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
/* showModal時の背景色カスタマイズ */
.hdlg-sec2-dialog::backdrop {
background-color: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(2px);
}
.hdlg-sec2-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-sec2-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-sec2-hl-blue {
color: #61afef;
font-weight: bold;
}
.hdlg-sec2-hl-red {
color: #e06c75;
font-weight: bold;
}
.hdlg-sec2-hl-comment {
color: #6c757d;
font-style: italic;
}setTimeout(() => {
const dialogShow = document.getElementById('dialogShow');
const dialogShowModal = document.getElementById('dialogShowModal');
const btnShow = document.getElementById('btnShow');
const btnShowModal = document.getElementById('btnShowModal');
const btnCloseShow = document.getElementById('btnCloseShow');
const btnCloseModal = document.getElementById('btnCloseModal');
if(btnShow && dialogShow) {
btnShow.addEventListener('click', () => dialogShow.show());
btnCloseShow.addEventListener('click', () => dialogShow.close());
btnShowModal.addEventListener('click', () => dialogShowModal.showModal());
btnCloseModal.addEventListener('click', () => dialogShowModal.close());
}
}, 100);「ページを開いた瞬間に、最初からお知らせを表示しておきたい」という場合、JavaScriptを使わずに表示させる方法がHTMLに用意されています。
それが<dialog>タグへのopen属性の追加です。
JavaScriptなしで開くopen属性は、あくまでページの一部に初めから表示しておく「非モーダルな案内版」として割り切って使用します。
また、open属性だけで開いたダイアログは、閉じるJavaScript(close())を書かない限り画面に残り続けます。
(※HTMLの<form method="dialog">を使えばJSなしでも閉じられますが、用途が限定的です。)
初期表示で「モーダル(背景暗転)」を出したい場合は、ページ読み込み直後にJavaScriptでdialog.showModal()を実行するのがよいです。
⭕️ HTMLに属性を書くだけで最初から表示されます
(背景は暗くならない)
<div class="hdlg-sec3-wrapper">
<div class="hdlg-sec3-demo-area">
<div class="hdlg-sec3-box">
<div class="hdlg-sec3-label">🚪 JSなしで開く open属性の仕様</div>
<div class="hdlg-sec3-visual">
<p style="font-size:12px; color:#0d6efd; font-weight:bold; margin:0 0 5px 0;">⭕️ HTMLに属性を書くだけで最初から表示されます</p>
<div class="hdlg-sec3-mock-bg">
<dialog open class="hdlg-sec3-mock-dialog">
<div style="margin:0 0 5px 0; font-size:14px;">メンテナンスのお知らせ</div>
<p style="font-size:11px; margin:0; color:#555;">※open属性で開いた場合は、必ず「非モーダル」になります。</p>
</dialog>
<p style="font-size:11px; color:#666; text-align:center; margin-top:80px;">(背景は暗くならない)</p>
</div>
</div>
<div class="hdlg-sec3-code">
<!-- ❌ 間違い:open属性でモーダル(背景暗転)にはならない --><br>
<dialog open>重要なお知らせ</dialog><br><br>
<!-- ⭕️ 完璧:HTMLの標準機能のみで「閉じる」ボタンを実装 --><br>
<dialog <span class="hdlg-sec3-hl-green">open</span>><br>
<p>お知らせ内容</p><br>
<span class="hdlg-sec3-hl-comment"><!-- ★ form method="dialog" 内のボタンは、押すとダイアログを閉じる --></span><br>
<span class="hdlg-sec3-hl-blue"><form method="dialog"></span><br>
<button>JSなしで閉じる</button><br>
<span class="hdlg-sec3-hl-blue"></form></span><br>
</dialog>
</div>
</div>
</div>
</div>.hdlg-sec3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-sec3-demo-area {
display: flex;
justify-content: center;
}
.hdlg-sec3-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-sec3-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-sec3-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
}
.hdlg-sec3-mock-bg {
background-color: #e9ecef;
border: 1px dashed #adb5bd;
border-radius: 4px;
position: relative;
height: 120px;
}
.hdlg-sec3-mock-dialog {
display: block; /* open状態の再現 */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
border: 1px solid #ced4da;
padding: 15px;
border-radius: 4px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
width: 80%;
margin: 0;
}
.hdlg-sec3-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-sec3-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-sec3-hl-blue {
color: #61afef;
font-weight: bold;
}
.hdlg-sec3-hl-red {
color: #e06c75;
font-weight: bold;
}
.hdlg-sec3-hl-comment {
color: #6c757d;
font-style: italic;
}<dialog>要素の真価は、JavaScriptと組み合わせた際の強力な標準APIにあります。
従来のライブラリに頼ることなく、ブラウザ標準の機能だけでモーダルの挙動を制御できるのがメリットです。
表示・非表示を切り替えるだけでなく、イベントハンドリングを正しく理解することで、ユーザーの操作に合わせた柔軟なUIを構築できます。
ここでは3つの実装パターンを解説します。
ダイアログを制御する基本は、JSのメソッド呼び出しです。
特に「閉じるボタン」を設置して、ユーザーが明示的に閉じられるようにすることはアクセシビリティの観点からも必須です。
ダイアログの開閉にはshowModal()(またはshow())とclose()メソッドを使用しましょう。
<div class="hdlg-js1-wrapper">
<div class="hdlg-js1-demo-area">
<div class="hdlg-js1-box">
<div class="hdlg-js1-label">🔘 showModalとcloseの制御</div>
<div class="hdlg-js1-visual">
<button id="js1-open" class="hdlg-js1-btn-main">モーダルを開く</button>
</div>
<dialog id="js1-dialog" class="hdlg-js1-dialog">
<div class="hdlg-js1-inner">
<p>標準APIで正しく制御されています。</p>
<button id="js1-close" class="hdlg-js1-btn-sub">閉じる</button>
</div>
</dialog>
<div class="hdlg-js1-code">
/* ⭕️ 正しい制御方法 */<br>
const dialog = document.getElementById('js1-dialog');<br><br>
// 開く処理<br>
openBtn.addEventListener('click', () => {<br>
<span class="hdlg-js1-hl-green">dialog.showModal();</span><br>
});<br><br>
// 閉じる処理<br>
closeBtn.addEventListener('click', () => {<br>
<span class="hdlg-js1-hl-green">dialog.close();</span><br>
});
</div>
</div>
</div>
</div>.hdlg-js1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-js1-demo-area {
display: flex;
justify-content: center;
}
.hdlg-js1-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-js1-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-js1-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
text-align: center;
}
.hdlg-js1-btn-main {
background-color: #0d6efd;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-js1-btn-sub {
background-color: #6c757d;
color: #fff;
border: none;
padding: 5px 15px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-js1-dialog {
margin: auto;
border: none;
border-radius: 8px;
padding: 0;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.hdlg-js1-inner {
padding: 30px;
text-align: center;
}
.hdlg-js1-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #0d6efd;
}
.hdlg-js1-hl-green {
color: #98c379;
font-weight: bold;
}setTimeout(() => {
const d = document.getElementById('js1-dialog');
const o = document.getElementById('js1-open');
const c = document.getElementById('js1-close');
if(o && d) o.onclick = () => d.showModal();
if(c && d) c.onclick = () => d.close();
}, 100);ダイアログが閉じられたことを検知して特定の処理を行いたい場合、dialogタグの閉じるイベントを利用します。
終了時の処理はボタンのクリックイベントではなく、<dialog>要素そのもののcloseイベントに対して設定しましょう。
また、dialog.close("戻り値")のように引数を渡すと、dialog.returnValueプロパティから「はい」「いいえ」などの選択結果を取得できます。
結果:未回答
<div class="hdlg-js2-wrapper">
<div class="hdlg-js2-demo-area">
<div class="hdlg-js2-box">
<div class="hdlg-js2-label">📝 closeイベントと戻り値の取得</div>
<div class="hdlg-js2-visual">
<button id="js2-open" class="hdlg-js2-btn-main">アンケートに答える</button>
<p id="js2-result" style="margin-top:15px; font-size:13px; color:#198754; font-weight:bold;">結果:未回答</p>
</div>
<dialog id="js2-dialog" class="hdlg-js2-dialog">
<div class="hdlg-js2-inner">
<p>この内容で送信しますか?</p>
<div style="display:flex; gap:10px; justify-content:center;">
<button class="js2-close-btn" data-val="yes" style="background:#198754; color:#fff; border:none; padding:5px 15px; border-radius:4px; cursor:pointer;">はい</button>
<button class="js2-close-btn" data-val="no" style="background:#dc3545; color:#fff; border:none; padding:5px 15px; border-radius:4px; cursor:pointer;">いいえ</button>
</div>
</div>
</dialog>
<div class="hdlg-js2-code">
// 閉じる時に値を渡す<br>
dialog.close(<span class="hdlg-js2-hl-green">'yes'</span>);<br><br>
// ★閉じられたことを検知する<br>
dialog.addEventListener(<span class="hdlg-js2-hl-red">'close'</span>, () => {<br>
console.log(dialog.<span class="hdlg-js2-hl-green">returnValue</span>);<br>
});
</div>
</div>
</div>
</div>.hdlg-js2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-js2-demo-area {
display: flex;
justify-content: center;
}
.hdlg-js2-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-js2-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-js2-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
text-align: center;
}
.hdlg-js2-btn-main {
background-color: #0d6efd;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-js2-dialog {
margin: auto;
border: none;
border-radius: 8px;
padding: 0;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.hdlg-js2-inner {
padding: 30px;
}
.hdlg-js2-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-js2-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-js2-hl-red {
color: #e06c75;
font-weight: bold;
}setTimeout(() => {
const d = document.getElementById('js2-dialog');
const o = document.getElementById('js2-open');
const r = document.getElementById('js2-result');
if(o && d) o.onclick = () => d.showModal();
document.querySelectorAll('.js2-close-btn').forEach(b => {
b.onclick = () => d.close(b.dataset.val);
});
if(d) d.onclose = () => r.textContent = `結果:${d.returnValue === 'yes' ? '送信しました' : 'キャンセルしました'}`;
}, 100);モーダル表示の際、ダイアログの外側(薄暗い背景部分)をクリックしたら閉じるようにしたいという要望は多いです。
背景クリックを判定するには、clickイベントの発生場所(座標)を確認します。
ダイアログ要素に対してクリックイベントを設定し、クリックされた位置が「ダイアログの矩形(枠)」の外側であればclose()を実行するというロジックがスマートで一般的です。
<div class="hdlg-js3-wrapper">
<div class="hdlg-js3-demo-area">
<div class="hdlg-js3-box">
<div class="hdlg-js3-label">🖱 背景クリックで閉じる判定</div>
<div class="hdlg-js3-visual">
<button id="js3-open" class="hdlg-js3-btn-main">背景クリックを試す</button>
</div>
<dialog id="js3-dialog" class="hdlg-js3-dialog">
<div class="hdlg-js3-inner">
<p style="font-weight:bold;">この「枠外」をクリックしてください</p>
<p style="font-size:12px; color:#666;">枠内をクリックしても閉じません。</p>
</div>
</dialog>
<div class="hdlg-js3-code">
dialog.addEventListener('click', (e) => {<br>
<span class="hdlg-js3-hl-comment">// クリックされた要素がdialog自身(背景)か判定</span><br>
if (e.target === <span class="hdlg-js3-hl-green">dialog</span>) {<br>
dialog.close();<br>
}<br>
});
</div>
</div>
</div>
</div>.hdlg-js3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-js3-demo-area {
display: flex;
justify-content: center;
}
.hdlg-js3-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-js3-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-js3-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
text-align: center;
}
.hdlg-js3-btn-main {
background-color: #0d6efd;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-js3-dialog {
margin: auto;
border: none;
border-radius: 8px;
padding: 0;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
/* 背景を少し分かりやすく */
.hdlg-js3-dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
.hdlg-js3-inner {
padding: 40px;
background-color: #fff;
pointer-events: auto;
}
.hdlg-js3-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-js3-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-js3-hl-comment {
color: #6c757d;
font-style: italic;
}setTimeout(() => {
const d = document.getElementById('js3-dialog');
const o = document.getElementById('js3-open');
if(o && d) o.onclick = () => d.showModal();
// 背景クリック判定:e.targetがdialog自身(子要素ではない)場合に閉じる
if(d) d.addEventListener('click', (e) => { if (e.target === d) d.close(); });
}, 100);JavaScriptでの基本的な開閉をマスターしたら、実際のWebアプリケーションで需要の高い「データ入力フォーム」や「実行確認」といった実用的なダイアログの作成になります。
ここでは、実務で使えるdialogのサンプル、CSSによるデザイン、javascriptの連携テクニックを解説します。
form method="dialog"の使い方<dialog>タグには、フォームと連携する専用機能が用意されています。
ダイアログ内に<form method="dialog">を配置すると、その中の送信ボタンを押した瞬間にJavaScriptのclose()メソッドを書かなくても自動的にダイアログが閉じます。
入力されたデータを実際にサーバーへ送りたい場合は、ダイアログが閉じた後に発生するcloseイベントをJavaScriptでキャッチし、fetc やXMLHttpRequest を使って非同期通信でデータを送信する設計にするのがよいです。
入力結果がここに表示されます
<div class="hdlg-prac1-wrapper">
<div class="hdlg-prac1-demo-area">
<div class="hdlg-prac1-box">
<div class="hdlg-prac1-label">📝 form method="dialog" の入力フォーム</div>
<div class="hdlg-prac1-visual">
<button id="prac1-open" class="hdlg-prac1-btn-main">プロフィールを編集</button>
<p id="prac1-result" style="margin-top:15px; font-size:13px; color:#666;">入力結果がここに表示されます</p>
</div>
<dialog id="prac1-dialog" class="hdlg-prac1-dialog">
<div class="hdlg-prac1-inner">
<div class="hdlg-prac1-title">プロフィール編集</div>
<form method="dialog" id="prac1-form">
<div class="hdlg-prac1-input-group">
<label class="hdlg-prac1-label-text">ユーザー名</label>
<input type="text" name="username" id="prac1-input" class="hdlg-prac1-input" placeholder="例:山田 太郎" required>
</div>
<div class="hdlg-prac1-actions">
<button type="submit" value="cancel" class="hdlg-prac1-btn-cancel" formnovalidate>キャンセル</button>
<button type="submit" value="save" class="hdlg-prac1-btn-submit">保存する</button>
</div>
</form>
</div>
</dialog>
<div class="hdlg-prac1-code">
<!-- 💡 フォームのmethodを dialog に設定する --><br>
<form <span class="hdlg-prac1-hl-green">method="dialog"</span>><br>
<input type="text" name="username"><br><br>
<!-- 💡 buttonのvalueがダイアログの戻り値になる --><br>
<button type="submit" <span class="hdlg-prac1-hl-blue">value="cancel"</span> formnovalidate>キャンセル</button><br>
<button type="submit" <span class="hdlg-prac1-hl-blue">value="save"</span>>保存</button><br>
</form>
</div>
</div>
</div>
</div>.hdlg-prac1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-prac1-demo-area {
display: flex;
justify-content: center;
}
.hdlg-prac1-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-prac1-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-prac1-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
text-align: center;
}
.hdlg-prac1-btn-main {
background-color: #0d6efd;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
.hdlg-prac1-dialog {
margin: auto;
border: none;
border-radius: 8px;
padding: 0;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
}
.hdlg-prac1-dialog::backdrop {
background-color: rgba(0, 0, 0, 0.6);
}
.hdlg-prac1-inner {
padding: 25px;
width: 300px;
}
.hdlg-prac1-title {
margin: 0 0 20px 0;
font-size: 18px;
color: #333;
}
.hdlg-prac1-input-group {
margin-bottom: 20px;
text-align: left;
}
.hdlg-prac1-label-text {
display: block;
font-size: 12px;
font-weight: bold;
margin-bottom: 5px;
color: #555;
}
.hdlg-prac1-input {
width: 100%;
padding: 10px;
border: 1px solid #ced4da;
border-radius: 4px;
box-sizing: border-box;
font-size: 14px;
}
.hdlg-prac1-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
}
.hdlg-prac1-btn-cancel {
background-color: #fff;
border: 1px solid #ced4da;
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
color: #495057;
}
.hdlg-prac1-btn-submit {
background-color: #198754;
color: #fff;
border: none;
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-prac1-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-prac1-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-prac1-hl-blue {
color: #61afef;
font-weight: bold;
}setTimeout(() => {
const dialog = document.getElementById('prac1-dialog');
const openBtn = document.getElementById('prac1-open');
const resultText = document.getElementById('prac1-result');
const inputEl = document.getElementById('prac1-input');
if(openBtn && dialog) {
openBtn.addEventListener('click', () => {
dialog.showModal();
});
}
if(dialog) {
dialog.addEventListener('close', () => {
// buttonのvalue属性の値('save' か 'cancel')が returnValue に入る
if (dialog.returnValue === 'save') {
resultText.textContent = `保存完了:${inputEl.value}`;
resultText.style.color = '#198754';
} else {
resultText.textContent = 'キャンセルされました';
resultText.style.color = '#dc3545';
}
});
}
}, 100);<form>タグの使い方を詳しく知りたい人は「【HTML】formタグの使い方:属性の書き方や複数送信・CSS装飾」を一読ください。
「データを削除しますか?」「本当に退会しますか?」といった場面で、昔から使われるwindow.confirm()(ブラウザ標準のアラート)はデザインが変更できず、現代のサイトには馴染みません。
そこで<dialog>を使って、おしゃれな「はい/いいえ」の確認画面を自作します。
自作の確認ダイアログの「はい」「いいえ」の結果を待ってから次の処理へ進めるには、JavaScriptのPromiseを使ってダイアログをラップするのがよいです。
処理結果がここに表示されます
<div class="hdlg-prac2-wrapper">
<div class="hdlg-prac2-demo-area">
<div class="hdlg-prac2-box">
<div class="hdlg-prac2-label">🚨 「はい/いいえ」のカスタムConfirm画面</div>
<div class="hdlg-prac2-visual">
<button id="prac2-open" class="hdlg-prac2-btn-main">アカウントを削除する</button>
<p id="prac2-result" style="margin-top:15px; font-size:13px; color:#666;">処理結果がここに表示されます</p>
</div>
<dialog id="prac2-dialog" class="hdlg-prac2-dialog">
<div class="hdlg-prac2-inner">
<div class="hdlg-prac2-icon">⚠️</div>
<div class="hdlg-prac2-title">本当に削除しますか?</div>
<p class="hdlg-prac2-text">この操作は取り消すことができません。アカウント内のすべてのデータが永久に失われます。</p>
<div class="hdlg-prac2-actions">
<button class="hdlg-prac2-btn-cancel js-confirm-btn" value="false">キャンセル</button>
<button class="hdlg-prac2-btn-danger js-confirm-btn" value="true">はい、削除します</button>
</div>
</div>
</dialog>
<div class="hdlg-prac2-code">
<!-- ❌ 致命的なミス:処理は止まらない --><br>
const result = dialog.showModal();<br>
if(result) { ... } <span class="hdlg-prac2-hl-comment">// ← ユーザーが押す前に実行されてしまう</span><br><br>
<!-- ⭕️ 大正解:Promiseでユーザーの操作を「待つ」 --><br>
<span class="hdlg-prac2-hl-blue">async function</span> handleDelete() {<br>
<span class="hdlg-prac2-hl-comment">// 自作の関数でダイアログの終了を待機</span><br>
const isConfirmed = <span class="hdlg-prac2-hl-blue">await</span> openConfirmDialog();<br><br>
if (isConfirmed === <span class="hdlg-prac2-hl-green">'true'</span>) {<br>
console.log("削除を実行しました");<br>
}<br>
}
</div>
</div>
</div>
</div>.hdlg-prac2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-prac2-demo-area {
display: flex;
justify-content: center;
}
.hdlg-prac2-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-prac2-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-prac2-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
text-align: center;
}
.hdlg-prac2-btn-main {
background-color: #dc3545;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
.hdlg-prac2-dialog {
border: none;
border-radius: 12px;
padding: 0;
box-shadow: 0 10px 25px rgba(0,0,0,0.3);
}
.hdlg-prac2-dialog::backdrop {
background-color: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(3px);
}
.hdlg-prac2-inner {
padding: 30px;
width: 320px;
text-align: center;
}
.hdlg-prac2-icon {
font-size: 40px;
margin-bottom: 10px;
}
.hdlg-prac2-title {
margin: 0 0 10px 0;
font-size: 18px;
color: #333;
}
.hdlg-prac2-text {
font-size: 13px;
color: #666;
line-height: 1.5;
margin: 0 0 25px 0;
}
.hdlg-prac2-actions {
display: flex;
gap: 10px;
}
.hdlg-prac2-btn-cancel {
flex: 1;
background-color: #e9ecef;
color: #333;
border: none;
padding: 12px;
border-radius: 6px;
cursor: pointer;
font-weight: bold;
}
.hdlg-prac2-btn-danger {
flex: 1;
background-color: #dc3545;
color: #fff;
border: none;
padding: 12px;
border-radius: 6px;
cursor: pointer;
font-weight: bold;
}
.hdlg-prac2-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #dc3545;
}
.hdlg-prac2-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-prac2-hl-blue {
color: #61afef;
font-weight: bold;
}
.hdlg-prac2-hl-comment {
color: #6c757d;
font-style: italic;
}setTimeout(() => {
const dialog = document.getElementById('prac2-dialog');
const openBtn = document.getElementById('prac2-open');
const resultText = document.getElementById('prac2-result');
const buttons = dialog.querySelectorAll('.js-confirm-btn');
// Promiseを使ってダイアログをラップする関数
function openCustomConfirm() {
return new Promise((resolve) => {
// ダイアログを表示
dialog.showModal();
// 一度だけ発火するイベントリスナーを登録
const handleClose = () => {
dialog.removeEventListener('close', handleClose);
resolve(dialog.returnValue);
};
dialog.addEventListener('close', handleClose);
});
}
// ボタンクリックで閉じる処理
buttons.forEach(btn => {
btn.addEventListener('click', (e) => {
dialog.close(e.target.value);
});
});
// メインの呼び出し処理(async/awaitを利用)
if(openBtn) {
openBtn.addEventListener('click', async () => {
resultText.textContent = "待機中...";
// ユーザーの選択を「待つ」
const isConfirmed = await openCustomConfirm();
if (isConfirmed === 'true') {
resultText.textContent = "処理:削除を実行しました。";
resultText.style.color = "#dc3545";
} else {
resultText.textContent = "処理:キャンセルされました。";
resultText.style.color = "#6c757d";
}
});
}
}, 100);<dialog>タグは標準状態で強力な機能を持ちますが、デフォルトの見た目はブラウザによって異なり、少し無骨な印象を与えます。
そのため、Webプロジェクトに導入する際は、CSSを駆使して、サイトに合わせたデザインを適用することが不可欠です。
ここでは、モーダルウィンドウの実装で直面する「サイズ・位置の調整」「背景の装飾」、ユーザー体験を向上させるアニメーションについて解説します。
ダイアログの見た目を整えるには、適切なサイズと幅を設定し、画面の正しい位置に配置することです。
ダイアログの配置はブラウザに任せ、CSSでは「幅(width/max-width)」と「内側の余白(padding)」だけを指定するのがよいです。
また、スマホ画面で全画面表示にしたい場合はwidth: 100vw; height: 100vh; max-width: none; max-height: none; margin: 0;のように、ブラウザのデフォルトマージンを打ち消す設定を行います。
<div class="hdlg-css1-wrapper">
<div class="hdlg-css1-demo-area">
<div class="hdlg-css1-box">
<div class="hdlg-css1-label">📐 サイズと表示位置の調整</div>
<div class="hdlg-css1-visual">
<div style="display:flex; gap:10px; justify-content:center;">
<button id="css1-btn-normal" class="hdlg-css1-btn-main">標準サイズで開く</button>
<button id="css1-btn-full" class="hdlg-css1-btn-sub">全画面(Full Screen)</button>
</div>
</div>
<dialog id="css1-dialog-normal" class="hdlg-css1-dialog-normal">
<div class="hdlg-css1-inner">
<div style="margin-top:0;">標準サイズ</div>
<p>max-widthを指定し、はみ出しを防ぎます。中央寄せはブラウザが自動で行います。</p>
<button class="js-css1-close hdlg-css1-btn-close">閉じる</button>
</div>
</dialog>
<dialog id="css1-dialog-full" class="hdlg-css1-dialog-full">
<div class="hdlg-css1-inner-full">
<div style="margin-top:0;">全画面表示</div>
<p>margin: 0; と width/height: 100%; で画面いっぱいに広げます。</p>
<button class="js-css1-close hdlg-css1-btn-close">閉じる</button>
</div>
</dialog>
<div class="hdlg-css1-code">
/* ⭕️ 標準サイズ(位置指定は不要) */<br>
<span class="hdlg-css1-hl-blue">dialog.normal</span> {<br>
<span class="hdlg-css1-hl-green">width: 90%;</span><br>
<span class="hdlg-css1-hl-green">max-width: 500px;</span><br>
border: none;<br>
}<br><br>
/* ⭕️ 全画面表示(フルスクリーン) */<br>
<span class="hdlg-css1-hl-blue">dialog.fullscreen</span> {<br>
<span class="hdlg-css1-hl-green">width: 100vw;</span><br>
<span class="hdlg-css1-hl-green">height: 100vh;</span><br>
<span class="hdlg-css1-hl-green">max-width: none;</span><br>
<span class="hdlg-css1-hl-green">max-height: none;</span><br>
<span class="hdlg-css1-hl-red">margin: 0;</span> /* ★ブラウザの自動マージンを消す */<br>
}
</div>
</div>
</div>
</div>.hdlg-css1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-css1-demo-area {
display: flex;
justify-content: center;
}
.hdlg-css1-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 550px;
border-radius: 4px;
}
.hdlg-css1-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-css1-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
text-align: center;
}
.hdlg-css1-btn-main {
background-color: #0d6efd;
color: #fff;
border: none;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-css1-btn-sub {
background-color: #212529;
color: #fff;
border: none;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-css1-btn-close {
background-color: #e9ecef;
border: 1px solid #ced4da;
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
margin-top: 15px;
}
/* 1. 標準サイズのダイアログCSS */
.hdlg-css1-dialog-normal {
width: 90%;
max-width: 400px;
border: none;
border-radius: 8px;
padding: 0;
margin: auto;
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
.hdlg-css1-inner {
padding: 30px;
text-align: center;
}
/* 2. 全画面サイズのダイアログCSS */
.hdlg-css1-dialog-full {
width: 100vw;
height: 100vh;
max-width: none;
max-height: none;
margin: 0; /* 必須 */
border: none;
padding: 0;
border-radius: 0;
}
.hdlg-css1-inner-full {
padding: 40px 20px;
text-align: center;
height: 100%;
box-sizing: border-box;
background-color: #fff;
}
.hdlg-css1-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-css1-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-css1-hl-blue {
color: #61afef;
font-weight: bold;
}
.hdlg-css1-hl-red {
color: #e06c75;
font-weight: bold;
}setTimeout(() => {
const dNormal = document.getElementById('css1-dialog-normal');
const dFull = document.getElementById('css1-dialog-full');
const bNormal = document.getElementById('css1-btn-normal');
const bFull = document.getElementById('css1-btn-full');
if(bNormal && dNormal) bNormal.onclick = () => dNormal.showModal();
if(bFull && dFull) bFull.onclick = () => dFull.showModal();
document.querySelectorAll('.js-css1-close').forEach(btn => {
btn.onclick = (e) => e.target.closest('dialog').close();
});
}, 100);要素に対する幅/高さ・中央寄せについて詳しく知りたい人は以下から一読ください。
モーダルダイアログの視認性を高める上で、背後のコンテンツを暗くしたり、すりガラスのようにぼかしたりするデザインは人気があります。
背景のデザインを変更するには、ダイアログ要素に対して::backdrop疑似要素を使用します。
背景を半透明の黒にするだけでなく、CSSプロパティであるbackdrop-filter: blur();を組み合わせることで、iOS風のすりガラス効果(ブラー効果)を実装できます。
背景の文字がぼやけるか確認してください
<div class="hdlg-css2-wrapper">
<div class="hdlg-css2-demo-area">
<div class="hdlg-css2-box">
<div class="hdlg-css2-label">🎨 背景(backdrop)のカスタマイズ</div>
<div class="hdlg-css2-visual">
<p style="font-size:16px; font-weight:bold; color:#0d6efd; margin-bottom:10px;">背景の文字がぼやけるか確認してください</p>
<button id="css2-btn" class="hdlg-css2-btn-main">すりガラス背景で開く</button>
</div>
<dialog id="css2-dialog" class="hdlg-css2-dialog">
<div class="hdlg-css2-inner">
<div style="margin-top:0;">すりガラス効果</div>
<p style="font-size:13px; color:#555;">backdrop-filterプロパティを使用しています。</p>
<button id="css2-btn-close" class="hdlg-css2-btn-close">閉じる</button>
</div>
</dialog>
<div class="hdlg-css2-code">
/* 💡 ダイアログそのもののデザイン */<br>
<span class="hdlg-css2-hl-blue">dialog</span> {<br>
border: none;<br>
border-radius: 8px;<br>
}<br><br>
/* 💡 ★背景(backdrop)のデザイン */<br>
<span class="hdlg-css2-hl-blue">dialog::backdrop</span> {<br>
<span class="hdlg-css2-hl-comment">/* 1. 背景を半透明の黒にする */</span><br>
<span class="hdlg-css2-hl-green">background-color: rgba(0, 0, 0, 0.4);</span><br><br>
<span class="hdlg-css2-hl-comment">/* 2. 背景をすりガラスのようにぼかす(5px分) */</span><br>
<span class="hdlg-css2-hl-green">backdrop-filter: blur(5px);</span><br>
}
</div>
</div>
</div>
</div>.hdlg-css2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
/* ぼかし効果を分かりやすくするための背景模様 */
background-image: radial-gradient(#adb5bd 1px, transparent 1px);
background-size: 20px 20px;
}
.hdlg-css2-demo-area {
display: flex;
justify-content: center;
}
.hdlg-css2-box {
background-color: rgba(255, 255, 255, 0.9);
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-css2-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-css2-visual {
padding: 20px;
margin-bottom: 20px;
text-align: center;
}
.hdlg-css2-btn-main {
background-color: #198754;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
.hdlg-css2-btn-close {
background-color: #e9ecef;
border: 1px solid #ced4da;
padding: 5px 15px;
border-radius: 4px;
cursor: pointer;
margin-top: 15px;
}
/* ダイアログとバックドロップのCSS */
.hdlg-css2-dialog {
margin: auto;
border: none;
border-radius: 12px;
padding: 0;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
}
.hdlg-css2-inner {
padding: 30px;
text-align: center;
}
/* ★背景のカスタマイズ */
.hdlg-css2-dialog::backdrop {
background-color: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(5px);
/* Safari対応 */
-webkit-backdrop-filter: blur(5px);
}
.hdlg-css2-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-css2-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-css2-hl-blue {
color: #61afef;
font-weight: bold;
}
.hdlg-css2-hl-comment {
color: #6c757d;
font-style: italic;
}setTimeout(() => {
const d = document.getElementById('css2-dialog');
const o = document.getElementById('css2-btn');
const c = document.getElementById('css2-btn-close');
if(o && d) o.onclick = () => d.showModal();
if(c && d) c.onclick = () => d.close();
}, 100);ダイアログがパッと一瞬で現れると、ユーザー体験(UX)としては唐突な印象を与えます。
ふわっと浮き出るようなアニメーションを追加することで、ユーザー体験を向上させます。
ダイアログが開く時のアニメーションを実装するには、transitionではなく、@keyframes(アニメーション定義)とdialog[open]属性セレクタを使用します。
(※なお「閉じる時」のアニメーションについては、CSS単体では実装できず、JavaScriptで閉じるタイミングを意図的に遅らせる複雑な処理が必要になるため、実務では「開く時のみフワッとさせる」のが手軽で効果的なベストプラクティスです。)
<div class="hdlg-css3-wrapper">
<div class="hdlg-css3-demo-area">
<div class="hdlg-css3-box">
<div class="hdlg-css3-label">✨ 開く時のアニメーション</div>
<div class="hdlg-css3-visual">
<button id="css3-btn" class="hdlg-css3-btn-main">アニメーション付きで開く</button>
</div>
<dialog id="css3-dialog" class="hdlg-css3-dialog">
<div class="hdlg-css3-inner">
<div style="margin-top:0;">Fade In & Scale Up</div>
<p style="font-size:13px; color:#555;">@keyframesを使用して、滑らかに表示させています。</p>
<button id="css3-btn-close" class="hdlg-css3-btn-close">閉じる</button>
</div>
</dialog>
<div class="hdlg-css3-code">
/* 💡 1. どんなアニメーションにするか定義する */<br>
<span class="hdlg-css3-hl-blue">@keyframes fadeInScale</span> {<br>
0% {<br>
<span class="hdlg-css3-hl-green">opacity: 0;</span><br>
<span class="hdlg-css3-hl-green">transform: scale(0.9) translateY(20px);</span><br>
}<br>
100% {<br>
<span class="hdlg-css3-hl-green">opacity: 1;</span><br>
<span class="hdlg-css3-hl-green">transform: scale(1) translateY(0);</span><br>
}<br>
}<br><br>
/* 💡 2. 開いた状態(open)になった時にアニメーションを実行 */<br>
<span class="hdlg-css3-hl-blue">dialog[open]</span> {<br>
<span class="hdlg-css3-hl-red">animation: fadeInScale 0.3s ease-out forwards;</span><br>
}<br><br>
/* おまけ:背景(backdrop)もフワッと暗くする */<br>
<span class="hdlg-css3-hl-blue">dialog[open]::backdrop</span> {<br>
<span class="hdlg-css3-hl-red">animation: backdropFade 0.3s ease-out forwards;</span><br>
}
</div>
</div>
</div>
</div>.hdlg-css3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-css3-demo-area {
display: flex;
justify-content: center;
}
.hdlg-css3-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-css3-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-css3-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
text-align: center;
}
.hdlg-css3-btn-main {
background-color: #0d6efd;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
.hdlg-css3-btn-close {
background-color: #e9ecef;
border: 1px solid #ced4da;
padding: 5px 15px;
border-radius: 4px;
cursor: pointer;
margin-top: 15px;
}
/* ダイアログの初期設定 */
.hdlg-css3-dialog {
margin: auto;
border: none;
border-radius: 12px;
padding: 0;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
}
.hdlg-css3-inner {
padding: 30px;
text-align: center;
}
/* ★ 1. ダイアログ本体のアニメーション定義 */
@keyframes hdlg-fade-in-scale {
0% {
opacity: 0;
transform: scale(0.9) translateY(20px);
}
100% {
opacity: 1;
transform: scale(1) translateY(0);
}
}
/* ★ 2. ダイアログ背景(backdrop)のアニメーション定義 */
@keyframes hdlg-backdrop-fade {
0% {
background-color: rgba(0, 0, 0, 0);
}
100% {
background-color: rgba(0, 0, 0, 0.5);
}
}
/* ★ 3. open属性がついた瞬間にアニメーションを発火 */
.hdlg-css3-dialog[open] {
animation: hdlg-fade-in-scale 0.3s ease-out forwards;
}
.hdlg-css3-dialog[open]::backdrop {
animation: hdlg-backdrop-fade 0.3s ease-out forwards;
}
.hdlg-css3-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-css3-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-css3-hl-blue {
color: #61afef;
font-weight: bold;
}
.hdlg-css3-hl-red {
color: #e06c75;
font-weight: bold;
}setTimeout(() => {
const d = document.getElementById('css3-dialog');
const o = document.getElementById('css3-btn');
const c = document.getElementById('css3-btn-close');
if(o && d) o.onclick = () => d.showModal();
if(c && d) c.onclick = () => d.close();
}, 100);様々な要素に対するCSSアニメーションの作り方を詳しく知りたい人は「【CSS】アニメーションの作り方:コピペで使えるおしゃれサンプル集」を一読ください。
<dialog>要素を実務のプロダクトに導入する際、画面の中央にポップアップを出すだけでは不十分です。
多様なユーザーが快適に操作できるためのアクセシビリティの担保、意図しない画面の動きを防ぐ属性の適切な設定が求められます。
ここでは、背景のスクロール問題の解決策、ブラウザ標準のフォーカス制御、最上位レイヤーの概念についてを解説します。
z-indexモーダルダイアログを開いている最中に、マウスホイールを回したりスマホ画面をスワイプすると、ダイアログの「後ろ(背景)」にある画面がスクロールする現象は、UXを著しく損ないます。
背景のスクロールを防ぐには、JavaScriptのイベントキャンセルではなく、overflow: hidden;を<body>要素に対して切り替えるのがよいです。
↓ 下にスクロールできます ↓
スクロールエリア
ダイアログを開くと、このスクロールができなくなります。
<div class="hdlg-adv1-wrapper">
<div id="adv1-scroll-area" class="hdlg-adv1-demo-area">
<div class="hdlg-adv1-box">
<div class="hdlg-adv1-label">🚫 背景スクロールの無効化(prevent scroll)</div>
<div class="hdlg-adv1-visual">
<button id="adv1-open" class="hdlg-adv1-btn-main">ダイアログを開く</button>
<p style="margin-top:20px; font-size:12px; color:#666;">
↓ 下にスクロールできます ↓<br><br><br>
スクロールエリア<br><br><br>
ダイアログを開くと、このスクロールができなくなります。
</p>
</div>
<dialog id="adv1-dialog" class="hdlg-adv1-dialog">
<div class="hdlg-adv1-inner">
<div style="margin-top:0;">スクロール停止中</div>
<p style="font-size:13px; color:#555;">後ろの画面はスクロールできません。</p>
<button id="adv1-close" class="hdlg-adv1-btn-close">閉じる</button>
</div>
</dialog>
<div class="hdlg-adv1-code">
/* 💡 1. スクロールを止めるCSSクラスを用意 */<br>
<span class="hdlg-adv1-hl-blue">body.no-scroll</span> {<br>
<span class="hdlg-adv1-hl-red">overflow: hidden !important;</span><br>
}<br><br>
/* 💡 2. JSでダイアログ開閉と同時にクラスを付け外しする */<br>
openBtn.addEventListener('click', () => {<br>
dialog.showModal();<br>
<span class="hdlg-adv1-hl-green">document.body.classList.add('no-scroll');</span><br>
});<br><br>
dialog.addEventListener('close', () => {<br>
<span class="hdlg-adv1-hl-green">document.body.classList.remove('no-scroll');</span><br>
});
</div>
</div>
</div>
</div>.hdlg-adv1-wrapper {
background-color: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-adv1-demo-area {
padding: 20px;
height: 400px;
overflow-y: auto;
}
.hdlg-adv1-demo-area.no-scroll {
overflow: hidden !important;
}
.hdlg-adv1-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
margin: 0 auto;
border-radius: 4px;
min-height: 600px;
box-sizing: border-box;
}
.hdlg-adv1-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-adv1-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
text-align: center;
}
.hdlg-adv1-btn-main {
background-color: #0d6efd;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
.hdlg-adv1-dialog {
border: none;
border-radius: 8px;
padding: 0;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
margin: auto !important;
}
.hdlg-adv1-dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
.hdlg-adv1-inner {
padding: 30px;
text-align: center;
}
.hdlg-adv1-btn-close {
background-color: #e9ecef;
border: 1px solid #ced4da;
padding: 5px 15px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-adv1-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-adv1-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-adv1-hl-blue {
color: #61afef;
font-weight: bold;
}
.hdlg-adv1-hl-red {
color: #e06c75;
font-weight: bold;
}setTimeout(() => {
const d = document.getElementById('adv1-dialog');
const o = document.getElementById('adv1-open');
const c = document.getElementById('adv1-close');
const area = document.getElementById('adv1-scroll-area');
if(o && d) {
o.addEventListener('click', () => {
d.showModal();
area.classList.add('no-scroll');
});
}
if(c && d) {
c.addEventListener('click', () => {
d.close();
});
}
if(d) {
d.addEventListener('close', () => {
area.classList.remove('no-scroll');
});
}
}, 100);overflowプロパティの使い方を詳しく知りたい人は「【html&css】overflowの使い方とhiddenやscrollの使い分け」を一読ください。
キーボード操作のみでブラウジングを行うユーザーにとって、ダイアログが開いた直後に「どこにフォーカス(選択状態)が当たっているか」は重要です。
<dialog>をshowModal()で開いた場合、フォーカストラップもESCキーで閉じる機能も、ブラウザが自動でやってくれます。
JSで自作する必要はありません。
ダイアログ内の「最初にフォーカスを当てたい要素(入力欄や閉じるボタン)」に対して、HTMLのautofocus属性を記述するだけです。
<div class="hdlg-adv2-wrapper">
<div class="hdlg-adv2-demo-area">
<div class="hdlg-adv2-box">
<div class="hdlg-adv2-label">🎯 autofocusとフォーカストラップ</div>
<div class="hdlg-adv2-visual">
<button id="adv2-open" class="hdlg-adv2-btn-main">検索ダイアログを開く</button>
</div>
<dialog id="adv2-dialog" class="hdlg-adv2-dialog">
<div class="hdlg-adv2-inner">
<div style="margin-top:0;">サイト内検索</div>
<input type="text" placeholder="キーワードを入力..." class="hdlg-adv2-input" autofocus>
<div style="margin-top:15px; font-size:12px; color:#555; text-align:left;">
<li>開いた瞬間、入力欄がアクティブになります。</li>
<li>Tabキーを押しても、外にフォーカスが逃げません。</li>
<li><strong>ESCキー</strong>を押すとダイアログが閉じます。</li>
</div>
<button id="adv2-close" class="hdlg-adv2-btn-close" style="margin-top:20px;">閉じる</button>
</div>
</dialog>
<div class="hdlg-adv2-code">
<!-- ❌ 間違い:JSで focus() や ESCキーの監視を書く --><br><br>
<!-- ⭕️ 大正解:HTMLに autofocus を書くだけ --><br>
<dialog><br>
<input type="text" <span class="hdlg-adv2-hl-green">autofocus</span>><br>
<button>検索</button><br>
</dialog><br>
<span class="hdlg-adv2-hl-comment"><!-- ※フォーカスを逃さない処理も、ESCキーで閉じる処理も、<br>
すべてブラウザ(showModal)が自動で行います。 --></span>
</div>
</div>
</div>
</div>.hdlg-adv2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-adv2-demo-area {
display: flex;
justify-content: center;
}
.hdlg-adv2-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-adv2-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-adv2-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
text-align: center;
}
.hdlg-adv2-btn-main {
background-color: #0d6efd;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
.hdlg-adv2-dialog {
margin: auto;
border: none;
border-radius: 8px;
padding: 0;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.hdlg-adv2-dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
.hdlg-adv2-inner {
padding: 30px;
text-align: center;
width: 250px;
}
.hdlg-adv2-input {
width: 100%;
padding: 10px;
border: 1px solid #ced4da;
border-radius: 4px;
box-sizing: border-box;
}
/* autofocus時の見た目を分かりやすく */
.hdlg-adv2-input:focus {
outline: 2px solid #0d6efd;
border-color: #0d6efd;
}
.hdlg-adv2-btn-close {
background-color: #e9ecef;
border: 1px solid #ced4da;
padding: 5px 15px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-adv2-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-adv2-hl-green {
color: #98c379;
font-weight: bold;
}
.hdlg-adv2-hl-comment {
color: #6c757d;
font-style: italic;
}setTimeout(() => {
const d = document.getElementById('adv2-dialog');
const o = document.getElementById('adv2-open');
const c = document.getElementById('adv2-close');
if(o && d) o.onclick = () => d.showModal();
if(c && d) c.onclick = () => d.close();
}, 100);Web制作で頭を悩ませる問題の一つが「z-indexの重なり順」です。
「ヘッダー(z-index: 9999)の下にモーダルが潜り込んでしまう」と焦った経験を持つ開発者は多いでしょう。
<dialog>をshowModal()で開いた場合、そもそもz-indexの概念自体が適用されません。
ブラウザは通常のHTMLの階層とは切り離された「Top Layer(最上位レイヤー」という特別な最前面の空間にダイアログを描画します。
そのため、背景のヘッダーがどれだけ巨大なz-indexを持っていようと、ダイアログは無条件で一番手前に表示されます。
(※なお、ダイアログをマウスでドラッグして移動させる機能は標準では備わっていないため、必要な場合は別途JavaScriptのライブラリ等で実装する必要があります。)
z-indexが9999のヘッダーがあっても、
dialogはそれを無視して必ず一番手前に出ます。
<div class="hdlg-adv3-wrapper">
<div class="hdlg-adv3-demo-area">
<div class="hdlg-adv3-box">
<div class="hdlg-adv3-label">👑 最上位レイヤー(Top Layer)の威力</div>
<div class="hdlg-adv3-visual">
<div class="hdlg-adv3-fake-header">
z-index: 9999 のヘッダー
</div>
<p style="margin-top:60px; font-size:12px; color:#555;">z-indexが9999のヘッダーがあっても、<br>dialogはそれを無視して必ず一番手前に出ます。</p>
<button id="adv3-open" class="hdlg-adv3-btn-main" style="margin-top:10px;">ダイアログを開く</button>
</div>
<dialog id="adv3-dialog" class="hdlg-adv3-dialog">
<div class="hdlg-adv3-inner">
<div style="margin-top:0; color:#dc3545;">私は Top Layer にいます</div>
<p style="font-size:13px;">z-indexの戦争から完全に解放されます。</p>
<button id="adv3-close" class="hdlg-adv3-btn-close">閉じる</button>
</div>
</dialog>
<div class="hdlg-adv3-code">
<!-- ❌ 間違い:z-indexで無理やり手前に出そうとする --><br>
<style><br>
dialog {<br>
<span class="hdlg-adv3-hl-red">z-index: 999999;</span><br>
}<br>
</style><br><br>
<!-- ⭕️ 大正解:何も指定しなくてよい --><br>
<span class="hdlg-adv3-hl-comment">/* showModal() で開かれた要素は、<br>
ブラウザ独自の「Top Layer(最上位レイヤー)」に配置されるため、<br>
すべてのz-indexを無視して必ず最前面に表示されます。 */</span>
</div>
</div>
</div>
</div>.hdlg-adv3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdlg-adv3-demo-area {
display: flex;
justify-content: center;
}
.hdlg-adv3-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 25px;
width: 100%;
max-width: 500px;
border-radius: 4px;
}
.hdlg-adv3-label {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.hdlg-adv3-visual {
background-color: #f1f3f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
text-align: center;
position: relative; /* 疑似ヘッダーの配置用 */
overflow: hidden;
}
/* z-index: 9999 を持たせた強敵の疑似ヘッダー */
.hdlg-adv3-fake-header {
position: absolute;
top: 0;
left: 0;
width: 100%;
background-color: #212529;
color: #fff;
padding: 10px 0;
font-weight: bold;
font-size: 14px;
z-index: 9999;
}
.hdlg-adv3-btn-main {
background-color: #198754;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
/* ★z-indexは一切指定していません */
.hdlg-adv3-dialog {
margin: auto;
border: none;
border-radius: 8px;
padding: 0;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
}
.hdlg-adv3-dialog::backdrop {
background-color: rgba(0, 0, 0, 0.6);
}
.hdlg-adv3-inner {
padding: 40px 30px;
text-align: center;
}
.hdlg-adv3-btn-close {
background-color: #e9ecef;
border: 1px solid #ced4da;
padding: 5px 15px;
border-radius: 4px;
cursor: pointer;
}
.hdlg-adv3-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
line-height: 1.6;
border-left: 4px solid #198754;
}
.hdlg-adv3-hl-red {
color: #e06c75;
font-weight: bold;
}
.hdlg-adv3-hl-comment {
color: #6c757d;
font-style: italic;
}setTimeout(() => {
const d = document.getElementById('adv3-dialog');
const o = document.getElementById('adv3-open');
const c = document.getElementById('adv3-close');
if(o && d) o.onclick = () => d.showModal();
if(c && d) c.onclick = () => d.close();
}, 100);重なり順を指定するz-indexプロパティの使い方を詳しく知りたい人は「【html&css】z-indexとは?使い方と効かない時の対処」を一読ください。
分かりやすいようにまとめを記載します。
<dialog>はブラウザネイティブのダイアログウィンドウを作成するHTML要素である。showModal()メソッドで開くと背景操作がブロックされるモーダルになり、show()メソッドでは非モーダルになる。open属性を付与すると初期表示できるが、常に非モーダルとして扱われる。<form method="dialog">を設置すると、送信ボタン押下時にJavaScript不要でダイアログが閉じる。margin: auto;(またはposition: fixed; inset: 0; margin: auto;)を指定する。::backdrop疑似要素で装飾できる。transitionではなく@keyframesとdialog[open]属性セレクタを組み合わせて実装する。closeイベントとreturnValueプロパティを使用する。e.target === dialog)を判定して実装する。body等へoverflow: hidden;を付与して制御する。showModal()で開かれたダイアログは最上位レイヤーに描画されるため、z-indexによる階層調整は不要である。<dialog>は、ポップアップ画面やモーダルウィンドウを簡単に作成するHTML5の標準タグです。
以前は複雑なJavaScriptや外部ライブラリが必要でしたが、ブラウザ標準の機能としてシンプルなコードでダイアログを実装できるようになりました。
主に「警告」「確認画面」「入力フォーム」などに使われます。
どちらもダイアログを開くJavaScriptメソッドですが、挙動が異なります。
show()は「非モーダル」として開き、背景を暗くせず、背後にあるページのボタンなどもそのままクリックできます。
一方、showModal()は「モーダル」として開き、背景の操作をブロックします。(標準で ::backdrop による背景暗転も適用されます。)
一般的なポップアップを作りたい場合は、基本的にshowModal()を使用します。
はい、一部可能です。
ページを開いた最初から表示させておきたい場合は、HTMLにopen属性(<dialog open>)をつけるだけで表示されます。(ただし非モーダルになります。)
また、ダイアログを「閉じる」動作は、ダイアログ内に<form method="dialog">を配置し、送信ボタン(<button>)を押すことで、JavaScript不要で閉じる標準機能が備わっています。
<dialog>の標準機能には背景クリックで閉じる仕様がないため、JavaScriptでコードを書く必要があります。
ダイアログに対してクリックイベントを設定し、クリックされた場所(e.target)がダイアログ要素だった場合」にclose()メソッドを実行する、という判定ロジックを追加するのが一般的な実装方法です。
最も多い原因は、サイト全体に適用している「リセットCSS」の影響です。
ブラウザは本来margin: auto;を使ってダイアログを中央に配置しますが、* { margin: 0; }などのリセットCSSが打ち消してしまうため、上にずれてしまいます。
解決するには、ダイアログのCSSに改めてmargin: auto !important;を指定し直すか、position: fixed; inset: 0;と組み合わせて強制的に中央へ固定してください。
サイト制作でお困りの人はお気軽にご連絡ください。
どんなお悩み事も丁寧に返信させて頂きます。
「どのサーバーを選べばいいか分からない…」そんな悩みを解決!
WordPressデビューに最適なサーバーを徹底比較しました。
