通知・ダイアログ
アラート(通知)
解説ありAlert
フォーカスを奪わずに重要メッセージを即座に読み上げる、live region を使った通知。
アラート(role="alert")とは?
アラートは、「保存しました」「エラーがあります」のような短い・重要なお知らせを、ユーザーの操作の流れを止めずに伝えるための仕組みです。 画面の隅に出るトースト通知や、フォーム送信後のメッセージなどが典型です。
ポイントは role="alert" を付けた領域をあらかじめ空のまま DOM に置いておき、 あとからJavaScriptでメッセージ文字列を差し込むこと。これだけでスクリーンリーダーが自動で読み上げてくれます。フォーカスは奪いません。
なぜアクセシビリティが大事なの?
目で画面を見られない/見えにくいユーザーを想像してください。
- スクリーンリーダーを使う人は、画面のどこかに出たメッセージに自分では気づけません。
role="alert"があれば、いま読んでいた場所を中断してでもその場で読み上げてくれます。 - 一方で、勝手にフォーカスを移してはいけません。 入力中だった場所が分からなくなり、かえって混乱させてしまいます。 アラートは「割り込んで読み上げる」だけで十分で、操作位置はユーザーに残します。
つまり「読み上げは割り込む/フォーカスは奪わない」が両立できるのがrole="alert" の良いところです。
ライブデモ(推奨実装)
下のボタンを押すと、ボタンの下にメッセージが表示されます。 このときフォーカスはボタンに留まったままです。
試してみよう:ボタンに Tab で移動 → Enter で「保存」。フォーカスはボタンのまま動かず、スクリーンリーダーだけがメッセージを読み上げます。
ポイント
スクリーンリーダー(macOSなら ⌘+F5 で VoiceOver)をオンにしてボタンを押すと、 フォーカスは動かないのに「入力内容を保存しました」と読み上げられます。 これが role="alert"(=割り込み読み上げ)の効果です。
キーボード操作
| キー | 動作 | 必須/任意 |
|---|---|---|
| (専用キーなし) | アラート自体に特別なキー操作はない。フォーカスを移さないのが正しい挙動。 | 必須 |
| Tab | メッセージを表示させるトリガー(ボタンなど)へは通常どおり移動できる。 | 必須 |
補足
アラートは「受け身の通知」です。閉じるボタンを付けるなら、それは普通の<button> としてキーボードで操作できるようにします(アラート領域自体にフォーカスは当てません)。
必要な WAI-ARIA / ロール
| 付ける場所 | 属性 / ロール | 意味 |
|---|---|---|
| 通知領域のコンテナ | role="alert" | 緊急の読み上げ領域にする。aria-live="assertive" 相当の挙動になる。 |
| 通知領域のコンテナ | aria-atomic="true"(任意) | 内容が変わったとき、領域全体をまとめて読み上げる。 |
| コンテナの設置タイミング | (属性ではなく実装) | 最初から空で DOM に置いておく。あとから文字を差し込むと読み上げられる。後から領域ごと挿入すると読まれないことがある。 |
実装:推奨パターン(Good)
良い例 / 推奨
空の role="alert" 領域を先に置き、あとからテキストだけを差し込みます。フォーカスは動かしません。
マークアップ:
<!-- ① 空の通知領域を最初から DOM に置いておく -->
<div id="status" role="alert"></div>
<button type="button" id="save">保存する</button>メッセージの差し込み:
const region = document.getElementById('status');
const button = document.getElementById('save');
button.addEventListener('click', () => {
// ② 後からテキストを差し込むと、role="alert" 領域は
// 自動で読み上げられる。フォーカスは button のまま動かさない。
region.textContent = '入力内容を保存しました。';
});補足
同じ文言を続けて入れると読み上げが繰り返されないことがあります。 回数表示を加える・一度空にしてから入れ直す、などで「内容が変わった」と認識させられます。 緊急でない通知(例:「自動保存しました」)は role="status"(=aria-live="polite")を使い、割り込まず読み上げるのが親切です。
アンチパターン(Bad)
下は role も aria-live も無い、ただの「見た目だけのバナー」です。目で見える人には伝わりますが、スクリーンリーダー利用者には何も伝わりません。
試してみよう:見た目はメッセージが出ますが、スクリーンリーダーでは無言のままです。重要なお知らせが完全に無視されてしまいます。
<!-- ❌ 見た目だけのバナー(role も aria-live も無い) -->
<button type="button" onclick="showBanner()">保存する</button>
<div id="banner" class="banner" style="display:none">
入力内容を保存しました。
</div>
<!-- 画面には出るが、スクリーンリーダーには何も伝わらない -->悪い例 / 避ける
この実装の問題点:
- 読み上げられない —
role="alert"もaria-liveも無いので、変化が通知されない。 - 気づけない — 画面の別の場所を読んでいるスクリーンリーダー利用者には存在自体が分からない。
- 逆に「読み上げさせたいから」とフォーカスを奪うのも誤り。操作位置を見失わせる。
ポイント
正解は「フォーカスは動かさず、role="alert" でテキストだけ差し込む」。 読み上げと操作位置の両方を尊重できます。
実装チェックリスト
role="alert"の領域を最初から空で DOM に置いている- メッセージは領域のテキストを差し替える形で挿入している
- アラート表示時にフォーカスを奪っていない
- 緊急でない通知は
role="status"(polite)を使い分けている - 同じ文言の再通知は内容を変化させて確実に読み上げさせている
- 閉じるボタンを付ける場合はキーボードで操作でき、フォーカスが見える