タイトル: 確認ウィンドウを表示する方法
SEOタイトル: JavaScript 確認ダイアログ完全ガイド (confirm / alert / prompt / dialog)
| この記事の要点 |
|
3 つのネイティブダイアログ
// 1. alert: 通知 (OK ボタンのみ)
alert('保存しました');
// 戻り値: undefined
// 2. confirm: 確認 (OK / Cancel)
const ok = confirm('削除してよろしいですか?');
if (ok) {
deleteItem();
} else {
console.log('キャンセルされた');
}
// 戻り値: true (OK) or false (Cancel / Esc / ×)
// 3. prompt: 入力
const name = prompt('お名前を入力してください', '匿名');
if (name !== null) {
console.log('入力された:', name);
} else {
console.log('キャンセル');
}
// 戻り値: 入力文字列 or null
典型的な使い方(削除確認)
<!-- インライン -->
<form action="/delete" method="POST"
onsubmit="return confirm('本当に削除しますか?')">
<button>削除</button>
</form>
<!-- イベントリスナー -->
<button id="delete-btn">削除</button>
<script>
document.getElementById('delete-btn').addEventListener('click', (e) => {
if (!confirm('元に戻せません。削除しますか?')) {
e.preventDefault();
return;
}
// 削除処理
});
</script>
ネイティブダイアログの問題点
| 問題 | 詳細 | 影響 |
|---|---|---|
| UI を完全ブロック | JavaScript の実行が停止する (同期的) | SPA / アニメーションが止まる |
| デザイン不可 | OS / ブラウザのスタイルそのまま | ブランドイメージに合わない |
| 多重表示で「無効化チェック」 | Chrome は「このサイトの追加ダイアログを禁止」を出す | 2 回目以降表示されない可能性 |
| モバイル UX が悪い | iOS / Android で表示が画面外 | 使い物にならないことも |
| 非同期処理と相性悪い | await の代わりに同期ブロック | パフォーマンス低下 |
| iframe では制限 | クロスオリジン iframe で動かないことも | 埋め込みウィジェットで失敗 |
HTML
HTML5 で標準化されたネイティブダイアログ。Promise ベースで非同期処理しやすい:
<dialog id="confirm-dialog">
<form method="dialog">
<p>本当に削除しますか?</p>
<menu>
<button value="cancel">キャンセル</button>
<button value="ok" autofocus>OK</button>
</menu>
</form>
</dialog>
<button id="open-btn">削除</button>
<script>
const dlg = document.getElementById('confirm-dialog');
document.getElementById('open-btn').addEventListener('click', () => {
dlg.showModal(); // ★ モーダル表示
});
dlg.addEventListener('close', () => {
if (dlg.returnValue === 'ok') {
console.log('削除実行');
} else {
console.log('キャンセル');
}
});
// Promise でラップ
function confirmDialog(message) {
return new Promise((resolve) => {
dlg.querySelector('p').textContent = message;
dlg.showModal();
dlg.addEventListener('close', () => {
resolve(dlg.returnValue === 'ok');
}, { once: true });
});
}
// 使い方
const ok = await confirmDialog('削除しますか?');
if (ok) { /* ... */ }
</script>
SweetAlert2 (人気ライブラリ)
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
const result = await Swal.fire({
title: '本当に削除しますか?',
text: 'この操作は元に戻せません',
icon: 'warning',
showCancelButton: true,
confirmButtonText: '削除する',
cancelButtonText: 'キャンセル',
confirmButtonColor: '#d33',
});
if (result.isConfirmed) {
await Swal.fire('削除しました', '', 'success');
}
// トースト風通知
Swal.fire({
toast: true,
position: 'top-end',
icon: 'success',
title: '保存しました',
timer: 3000,
showConfirmButton: false,
});
</script>
React でのカスタムモーダル
import { useState } from 'react';
function ConfirmModal({ open, message, onConfirm, onCancel }) {
if (!open) return null;
return (
<div className="modal-backdrop">
<div className="modal">
<p>{message}</p>
<button onClick={onConfirm}>OK</button>
<button onClick={onCancel}>Cancel</button>
</div>
</div>
);
}
function DeleteButton() {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>削除</button>
<ConfirmModal
open={open}
message="削除しますか?"
onConfirm={() => { doDelete(); setOpen(false); }}
onCancel={() => setOpen(false)}
/>
</>
);
}
Vue.js でのカスタムモーダル
<template>
<button @click="show = true">削除</button>
<div v-if="show" class="modal">
<p>削除しますか?</p>
<button @click="confirm">OK</button>
<button @click="show = false">Cancel</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const show = ref(false);
const emit = defineEmits(['confirmed']);
function confirm() {
emit('confirmed');
show.value = false;
}
</script>
アクセシビリティ (a11y) 配慮
- カスタムモーダルには
role="dialog"+aria-modal="true" - キーボードでフォーカストラップ (Tab が外に出ないように)
- Esc キーで閉じられるように
- 背景に
aria-hidden="true"をかけて読み上げ阻止 - ネイティブ
<dialog>はこれら全部自動でやってくれる
選択指針
| シチュエーション | 推奨 |
|---|---|
| 社内ツール / プロトタイプ | confirm() でOK |
| モダンブラウザ対応の Web アプリ | <dialog> 要素 |
| 美しいデザイン重視 | SweetAlert2 / カスタムモーダル |
| React / Vue / Svelte SPA | コンポーネント化されたカスタムモーダル |
| IE11 サポート(既に終了) | jQuery UI Dialog / Bootstrap Modal |
FAQ
Q: confirm() で「キャンセル」を Esc キーで返せる?
A: 多くのブラウザで Esc は Cancel (false) 扱い。× ボタンも同じく false。
Q: <dialog> はどこから使える?
A: Chrome 37+ / Firefox 98+ / Safari 15.4+。2024 年以降は主要モダンブラウザ全対応。
Q: confirm を await 風に書ける?
A: confirm() 自体は同期。await したいなら <dialog> や SweetAlert2 のような Promise ベース API を使ってください。