WCAG 達成基準 · Level AA

WCAG 4.1.3: ステータスメッセージ

WCAG 4.1.3 は、フォーム送信の確認、エラー通知、カートの更新などのステータスメッセージが、ロールまたはプロパティを通じてプログラム的に判別可能であることを求めています。これにより、ユーザーがフォーカスを移動することなく、支援技術がそれらを読み上げられるようにします。これによって、スクリーンリーダーに依存するユーザーが、フォーカスがメッセージに移動しない場合でも重要なフィードバックを受け取れるようになります。

この規定が意味すること

WCAG 達成基準 4.1.3「ステータスメッセージ」(レベル AA。WCAG 2.1 で導入され、WCAG 2.2 に引き継がれています)は次のように定めています。「マークアップ言語を用いて実装されたコンテンツにおいて、ステータスメッセージはロールまたはプロパティを通じてプログラムによる解釈が可能であり、フォーカスを受け取ることなく支援技術によって利用者に提示できる。」

実務的には、インターフェイスが結果を利用者に知らせるメッセージを生成するたびに — 検索で結果が返ってきたとき、フォーム送信が成功したとき、ショッピングカートに商品が追加されたとき、バリデーション後にエラーが発生したとき、あるいは処理が完了したときなど — そのメッセージは、利用者がそこへ移動しなくてもよい形で支援技術(AT)に公開されていなければなりません。重要な制約は、そのメッセージがキーボードフォーカスやプログラムによるフォーカスを受け取ることに依存せずに読み上げられる必要がある、という点です。

この達成基準は、マークアップ言語(HTML、SVG など)で記述されたあらゆるコンテンツに適用され、WCAG が認めるステータスメッセージの 4 つの大きなカテゴリを対象とします。

  • 成功メッセージ: 「ご注文を受け付けました」や「設定は正常に保存されました」のような確認メッセージ。
  • エラーまたは警告メッセージ: 「メールアドレスが正しくありません」や「必須項目をすべて入力してください」のようなバリデーションフィードバック。
  • 進行状況やステータスの更新: 「読み込み中…お待ちください」や「アップロード 60% 完了」のようなメッセージ。
  • コンテキストの変化を示すメッセージ: 「5 件の結果が見つかりました」や「カートに 3 点入っています」のような動的な更新。

メッセージがこの達成基準に適合しているのは、適切な ARIA ライブリージョンのロールまたはプロパティ — 一般的には role="status"role="alert"aria-live="polite"aria-live="assertive" — が割り当てられており、ユーザーがタブ移動しなくても、メッセージが表示または変更されたときにスクリーンリーダーが自動的に読み上げる場合です。

メッセージが不適合となるのは、(JavaScript を通じて)DOM に動的に挿入されているにもかかわらず、ライブリージョンのセマンティクスを持たないため、スクリーンリーダー利用者がページ上で何かが変化したことに気づけない場合です。

WCAG によって定義されている重要な例外があります。ステータスメッセージが、そのメッセージ要素にフォーカスを移動することで提示される場合(たとえばフォーカスを受け取るダイアログや alert() ダイアログなど)、そのインタラクションにはこの達成基準は適用されません。フォーカス移動そのものがニーズを満たすからです。この達成基準が対象としているのは、フォーカスの変更なしに表示されるメッセージです。

なぜ重要か

スクリーンリーダー利用者は、ページを直線的に、あるいはランドマーク、見出し、インタラクティブなコントロール間をジャンプしながら操作します。ページが DOM に「メッセージが送信されました」といったバナーを黙って挿入し、何も読み上げない場合、盲の利用者はその操作が成功したことを知る術がありません。フォームを再送信したり、いつまでも待ち続けたり、混乱してタスクを放棄してしまうかもしれません。同じ問題は、ズームや拡大表示に依存するロービジョンの利用者にも影響します。現在のビューポートの外側に表示されるステータスメッセージは、音声で読み上げられない限り気づかれません。

スイッチアクセスや視線入力技術に依存する運動障害のある利用者も同様に影響を受けます。これらの利用者は、ページ上の新しいコンテンツを素早く走査することが難しく、関連情報が AT によって届けられることに依存しています。ライブリージョンによる読み上げがなければ、すべてのステータス更新は「干し草の山から針を探す」問題になってしまいます。

認知特性の多様な利用者にもメリットがあります。明確で即時のフィードバックは、操作が完了したことを確認し、不確実さによる認知的負荷を軽減します。AT が「商品をカートに追加しました」と読み上げれば、認知障害のある利用者は、先に進む前に視覚的に確認を探し回る必要がありません。

具体的な実例として、盲の利用者がトルコの銀行のウェブサイトで複数項目の保険申込フォームに入力している場面を考えます。フォームを送信すると、クライアントサイドのバリデーションが動作し、項目の近くに赤いエラーメッセージが 5 つ表示されます。しかしライブリージョンが存在しないため、利用者のスクリーンリーダー(JAWS や NVDA)は何も読み上げません。利用者はフォームが正常に送信されたと誤解し、ブラウザのタブを閉じてしまい、申込内容をすべて失ってしまいます。適切に実装された role="alert" や要約用ライブリージョンがあれば、AT はすぐに「3 件のエラーが見つかりました。ハイライトされた項目を確認してください」と読み上げ、利用者は問題を修正できたはずです。

ビジネスの観点から見ると、アクセシブルでないステータスフィードバックはコンバージョン率を直接損ないます。世界で約 13 億人が何らかの障害とともに暮らしており、ステータスメッセージをアクセシブルにすることは、フォーム離脱率、サポートチケット件数、そして非準拠に伴う法的リスクを減らすことにつながります。トルコの組織にとっては、アクセシビリティの欠如が、後述する障害者法第 5378 号および新しい大統領通達に基づく義務違反となる可能性もあります。

関連する axe-core のルール

  • aria-live(自動テスト): axe-core の aria-live ルールは、aria-live 属性を使用している要素に、offpoliteassertive のいずれかの有効な値が割り当てられているかをチェックします。aria-live="true"aria-live="yes" のように、aria-live が無効またはスペルミスの値に設定されている要素を検出します。こうした値は、ライブリージョンが支援技術によって黙って無視される原因になります。このルールは、開発者がライブリージョンを作成しようとしたときに、その属性が正しく記述され、スクリーンリーダーが確実にそれを解釈できるようにするためのものです。
  • 手動テスト(完全なカバレッジには必須): 自動ツールは WCAG 4.1.3 を完全には監査できません。主な失敗パターンは、動的に生成されるメッセージにライブリージョンが存在しないことですが、静的コード解析ではこの「不在」を確実に検出するのが難しいためです。ユーザー操作の前に DOM をスキャンするツールは、どの要素が後にステータスメッセージになるかを知ることができません。スキャン時点で div が空であったり、まだ存在していなかったりするため、axe-core はボタンクリック後にテキストが挿入される <div> を検出しないかもしれません。そのため、実際のスクリーンリーダーを用いた手動テストが不可欠です。テスターはステータスメッセージを発生させ、その読み上げを確認しなければなりません。読み上げがなく、フォーカスも移動していない場合は、自動ツールの結果にかかわらず、この達成基準は不適合となります。

テスト方法

  1. axe DevTools または Lighthouse による自動スキャン: axe DevTools ブラウザ拡張機能(Chrome または Firefox)をインストールし、ページ全体のスキャンを実行します。aria-live ルールの下にある違反を確認します。また、aria-roledescriptionaria-atomic の誤用としてフラグされた問題も確認します。自動スキャンで問題が検出されなかったからといって、4.1.3 に適合しているとは限りません。これは単に、誤ったライブリージョン属性が見つからなかったことを意味するだけです。フラグされた要素をすべて記録し、手動ステップに進む前に解決してください。
  2. すべての動的ステータスメッセージを特定する: ページとその JavaScript を確認し、ページリロードやフォーカス変更なしにステータスメッセージを生成するすべてのユーザー操作を洗い出します。よくある例として、フォーム送信のフィードバック、カート数量バッジ、検索結果件数、ファイルアップロードの進行状況、ニュースレター登録の確認、フィルター結果の更新、セッションタイムアウト警告などがあります。
  3. NVDA + Firefox による手動テスト: NVDA を起動した状態でページを開きます。洗い出した各ステータスメッセージを発生させます(フォーム送信、カートへの商品追加、検索の実行など)。注意深く聞き、1〜2 秒以内に NVDA がメッセージのテキストを自動的に読み上げることを確認します。何も聞こえず、フォーカスも移動していない場合は不適合です。NVDA のスピーチビューア(Tools > Speech Viewer)を使って、すべての読み上げ内容のテキストログを確認し、正確性を検証します。
  4. JAWS + Chrome による手動テスト: 同じ操作を JAWS で繰り返します。role="status" のメッセージが穏やかな割り込み(polite)として読み上げられ、role="alert" のメッセージが即座に割り込んで読み上げられることを確認します。また、不適切な aria-atomicaria-relevant の設定により、JAWS が同じメッセージを複数回読み上げていないか確認します。
  5. VoiceOver + Safari(macOS/iOS)による手動テスト: macOS 上で VoiceOver と Safari を使用し、同じ操作を繰り返します。VoiceOver の aria-live の扱いは Windows のスクリーンリーダーとやや異なる場合があるため、読み上げが行われ、内容が適切に表現されていることを確認します。
  6. 操作後の DOM を検査する: ブラウザの DevTools を使い、ステータスメッセージを発生させた後に表示された要素を検査します。その要素に role="status"role="alert"、または有効な aria-live 属性が付与されていることを確認します。メッセージが、マークされていないコンテナにプレーンテキストとして挿入されている場合は不適合です。また、ライブリージョンのコンテナが、メッセージが挿入される前に DOM に存在していたかどうかも確認します。スクリーンリーダーは、既存のライブリージョンの変更のみを読み上げ、新たに DOM に挿入された要素の変化は読み上げないことが多いためです。

修正方法

フォームバリデーションのサマリー — 不適切な例

<!-- Error summary injected after failed submission -->
<div id='error-summary' class='error-box'>
  <p>Please fix the following errors before submitting:</p>
  <ul>
    <li>Email address is required.</li>
    <li>Password must be at least 8 characters.</li>
  </ul>
</div>
<!-- Problem: no role or aria-live attribute; screen readers will not announce this -->

フォームバリデーションのサマリー — 適切な例

<!-- role="alert" causes immediate announcement when content is injected -->
<div id='error-summary' role='alert' class='error-box'>
  <p>Please fix the following errors before submitting:</p>
  <ul>
    <li>Email address is required.</li>
    <li>Password must be at least 8 characters.</li>
  </ul>
</div>
<!-- The container must be present in the DOM before JavaScript injects content into it -->

ショッピングカートの商品数 — 不適切な例

<!-- Cart badge updated via JavaScript after user clicks "Add to cart" -->
<button id='add-to-cart'>Add to Cart</button>
<span id='cart-count' class='badge'>0</span>
<!-- Problem: cart-count has no live region; update from 0 to 1 is silent to screen readers -->

ショッピングカートの商品数 — 適切な例

<!-- Separate polite live region announces cart update without interrupting the user -->
<button id='add-to-cart'>Add to Cart</button>
<span id='cart-count' class='badge' aria-hidden='true'>1</span>

<!-- Visually hidden live region provides the announcement -->
<div
  id='cart-status'
  role='status'
  aria-live='polite'
  aria-atomic='true'
  class='visually-hidden'
>
  <!-- JavaScript updates this text: "1 item in your cart" -->
</div>
<!-- aria-atomic="true" ensures the full sentence is read, not just the changed number -->

検索結果件数 — 不適切な例

<!-- Results count rendered after AJAX search -->
<p id='results-info'>Showing 24 of 140 results for "laptop"</p>
<!-- Problem: element is replaced entirely via innerHTML; no live region present -->

検索結果件数 — 適切な例

<!-- Live region pre-exists in the DOM; JavaScript updates its content after search -->
<p
  id='results-info'
  role='status'
  aria-live='polite'
  aria-atomic='true'
>
  Showing 24 of 140 results for "laptop"
</p>
<!-- role="status" implies polite + atomic; explicit attributes added for clarity and compatibility -->

ファイルアップロードの進行状況 — 不適切な例

<!-- Progress percentage injected into DOM during upload -->
<div class='progress-container'>
  <div class='progress-bar' style='width: 60%'></div>
  <span id='progress-text'>60%</span>
</div>
<!-- Problem: percentage updates are visual only; no announcement to AT -->

ファイルアップロードの進行状況 — 適切な例

<!-- Use aria-valuenow on a progressbar role, plus a separate polite status for milestones -->
<div class='progress-container'>
  <div
    role='progressbar'
    aria-valuenow='60'
    aria-valuemin='0'
    aria-valuemax='100'
    aria-label='File upload progress'
    class='progress-bar'
    style='width: 60%'
  >
  </div>
</div>
<div
  id='upload-status'
  role='status'
  aria-live='polite'
  aria-atomic='true'
  class='visually-hidden'
>
  Upload complete. Your file has been saved.
</div>
<!-- Only announce key milestones (25%, 50%, 75%, complete) to avoid over-announcement -->

よくある間違い

  • メッセージと同時にライブリージョン要素を作成する: 新しく作成した DOM 要素に role="alert" を付与し、すぐに内容を挿入しても、多くの場合スクリーンリーダーはその新しいノードをライブリージョンとしてまだ認識していないため、読み上げに失敗します。空のコンテナは必ずページ読み込み時にレンダリングし、ステータスメッセージが準備できたときにのみテキスト内容を更新してください。
  • 緊急性の低いメッセージに aria-live="assertive" を使う: assertive なライブリージョンは、スクリーンリーダーが読み上げている内容を中断します。「商品をカートに追加しました」のような日常的なメッセージに assertive を使うと、読み上げが頻繁に遮られ、利用者を苛立たせます。assertive(または role="alert")は、本当に時間的制約のあるエラーや警告に限定し、それ以外には polite を使用してください。
  • aria-live"true""1" などの無効な値を設定する: 有効な値は "off""polite""assertive" のみです。無効な値はブラウザの警告なしにライブリージョンを黙って無効化し、axe-core の aria-live ルールによってフラグされます。
  • ステータスの伝達に色やアイコンだけを頼る: ページに挿入された緑のチェックマークアイコンや赤い枠線は、視覚的なシグナルに過ぎません。ライブリージョン内のテキストを伴わなければ、スクリーンリーダー利用者には何の情報も伝わりません。視覚的なインジケーターには、必ずテキストベースのライブリージョンによる読み上げを組み合わせてください。
  • 文の一部だけを更新する際に aria-atomic="true" を省略する: JavaScript が文中の数字だけを更新する場合(例: 「カートに 4 点」の「3」を「4」に変更するなど)、スクリーンリーダーによっては変更されたノードだけを読み上げ、「4」とだけ言って文脈を伝えないことがあります。コンテナに aria-atomic="true" を設定すると、AT はリージョン全体をひとまとまりとして読み上げるようになります。
  • 進行状況のすべての増分を読み上げる: ファイルアップロード中に毎秒新しいステータスメッセージ(「10%」「11%」「12%」…)を挿入すると、利用者は読み上げの洪水にさらされ、スクリーンリーダーが使い物にならなくなります。意味のあるマイルストーンや最終的な完了状態だけを読み上げるようにしてください。
  • ライブリージョンのコンテナを display:nonevisibility:hidden で条件付き非表示にされる要素の内側に置く: 非表示の親要素の内側にあるライブリージョンは機能せず、たとえライブリージョン要素自体が可視であっても何も読み上げません。読み上げ時点で、ライブリージョンの祖先要素が非表示になっていないことを確認してください。
  • ナビゲーション後に表示される成功メッセージに role="alert" を使う: ステータスメッセージがページリロードをまたいで持続する場合(リダイレクト後にサーバーサイドでレンダリングされるフラッシュメッセージなど)、role="alert" を使うと、重複したり過度に強い読み上げを引き起こすことがあります。代わりに role="status" を検討するか、メッセージ領域にフォーカスを移動して、読み上げが利用者のナビゲーションの流れに自然に統合されるようにしてください。
  • ツールチップやトーストのライブラリが自動的にライブリージョンを処理していると想定する: 多くの一般的な UI コンポーネントライブラリ(例: Bootstrap Toasts やカスタムツールチップシステム)は、デフォルトでは ARIA ライブリージョン属性を追加しません。サードパーティコンポーネントのレンダリングされた HTML を必ず確認し、必要に応じて role="status"aria-live を追加してください。
  • リリース前に実際のスクリーンリーダーでテストしない: axe のような自動ツールは、動的なステータスメッセージにライブリージョンが存在しないことを検出できません。自動監査だけに頼ると、4.1.3 の不適合が見逃されます。動的なフィードバックを生成する機能については、NVDA、JAWS、VoiceOver を用いた手動のスクリーンリーダーテストを QA プロセスの標準としてください。

トルコのアクセシビリティ規制との関係

トルコの大統領通達第 2025/10 号は、2025 年 6 月 21 日付官報第 32933 号で公布され、トルコで事業を行う幅広い組織に対して、拘束力のあるデジタルアクセシビリティ義務を定めています。この通達は、準拠のための技術標準として WCAG 2.1 および WCAG 2.2 を参照し、多くの対象組織に対してレベル AA での適合をベースラインとして求めています。

WCAG 4.1.3「ステータスメッセージ」はレベル AA の達成基準であり、通達の対象となるすべての組織にとって、義務の範囲に直接含まれます。以下のような組織種別が明示的に対象とされています。

  • 公的機関・団体 — すべての中央・地方政府機関、省庁、自治体、国営企業は、デジタルサービス全般で AA 準拠を満たさなければなりません。
  • 銀行および金融機関 — 銀行規制監督庁(BDDK)の規制対象であり、インターネットバンキング、ローン申込、カード管理などの重要なオンラインサービスを提供しています。ここでは、取引の確認、エラーメッセージ、残高更新など、動的なステータスフィードバックが非常に頻繁に発生します。4.1.3 の不適合は、障害のある利用者の経済的自立を直接妨げます。
  • EC プラットフォーム — オンライン小売は、ステータスメッセージ(カート更新、注文確認、在庫アラート)の主要なユースケースです。EC 事業者は、これらの動的通知がすべての利用者にとってアクセシブルであることを保証しなければなりません。
  • 病院および医療機関 — 予約システム、検査結果ポータル、患者ダッシュボードでは、ステータスメッセージが頻繁に使用されます。アクセシブルでない医療情報は、障害のある患者に深刻な影響を及ぼす可能性があります。
  • 20 万人以上の加入者を持つ通信会社 — アカウント管理ポータル、請求通知、サービスステータスの更新は、すべてレベル AA に準拠しなければならず、4.1.3 も含まれます。
  • 旅行代理店および民間交通事業者 — 予約確認、座席選択のフィードバック、旅程更新メッセージはユーザー体験の中核であり、プログラムによる解釈が可能でなければなりません。
  • 国民教育省(MoNE)に認可された私立学校および教育機関 — 学習管理システム、成績ポータル、入学手続きプラットフォームは、すべての生徒と保護者にサービスを提供するために、ステータスメッセージをアクセシブルな形で公開しなければなりません。

アクセシビリティロゴ(Erişilebilirlik Logosu)は、家族・社会サービス省が発行する、トルコのデジタルアクセシブルなウェブサイトやアプリケーションの公式認証マークです。このロゴを取得するには、組織はレベル AA への完全な適合を証明しなければならず、その中には 4.1.3 も含まれます。ステータスメッセージは現代のウェブインターフェイスにおいて遍在しているため、Erişilebilirlik Logosu を目指す組織は、4.1.3 を必須の監査項目として扱い、すべての動的コンテンツ領域でライブリージョンのパターンを一貫して実装すべきです。

準拠しない組織は、通達に基づく行政措置のリスク、アクセシビリティロゴの取得資格の喪失、そしてアクセシビリティへの意識が高まる市場における評判の低下に直面します。WCAG 4.1.3 を正しく実装することは、単なる技術的なチェック項目ではなく、障害のある約 850 万人のトルコ市民に対する、平等なデジタルアクセスへの具体的な投資なのです。