person holding black android smartphone
Photo by cottonbro studio on Pexels.com
目次

エラーメッセージとマイクロコピーのアクセシビリティ完全ガイド:迷わせない言葉、疲れさせない通知、確実に直せる導線

概要サマリー(先に要点)

  • “何が問題か/どこで起きたか/どう直すか” を1メッセージで完結させ、色だけに頼らない重複伝達(テキスト+アイコン+コントラスト)を行います。
  • 要約エリア+各項目の個別エラーの二段構え、**role="alert"role="status" の使い分け、フォーカス移動で修正を最短化。
  • 予防的マイクロコピー(例・制約・ヒント)でエラー発生を最小化し、リアルタイム検証は控えめに。
  • 非同期/ネットワーク/権限/競合など“フォーム外”の失敗も含め、回復手段(再試行・下書き保存・連絡先)を明示。
  • 実装スニペット(HTML/ARIA/CSS/JS)、文例テンプレ5分スモークテスト組織の言語スタイルガイドの作り方まで収録。

対象読者(具体):プロダクトマネージャー、UI/UXデザイナー、テクニカルライター、フロントエンドエンジニア、QA/CS、ドキュメント担当
アクセシビリティレベルWCAG 2.1 AA 準拠を基準(可能箇所は AAA を志向)。1.3.1/1.4.1/1.4.3/1.4.11/2.1.1/2.2.2/2.4.3/2.4.6/2.4.7/3.3.x/4.1.2 を中心に対応


1. はじめに:エラーは“叱る”ためではなく“助ける”ためにあるの

エラーメッセージは、ユーザーの“つまずき”を次の一歩へと導く小さな手です。
怒ったような赤文字や専門用語の羅列は、認知負荷と不安を高め、離脱の引き金になります。
わたしたちが目指すのは、落ち着いた言葉確実な修正手順、そして誰の状況でも読める・気づける表現。
アクセシビリティは、視覚・聴覚・運動・認知の多様性や、片手操作・騒音・低速回線・小画面といった“環境の揺れ”にも効きます。
このガイドでは、設計→文案→実装→検証→運用の順で、現場でそのまま使える型をご紹介しますね。


2. 大原則:3点セットで“即、直せる”

2.1 メッセージの黄金比(What / Where / How)

  • What(何が問題?):具体的事実を短く。「郵便番号は7桁の数字ではありません」。
  • Where(どこで?):該当フィールドをテキストで特定。「郵便番号」。
  • How(どう直す?):修正方法を一文で。「ハイフンなしの7桁で入力してください(例:1000001)」。

例(良い):「郵便番号が未入力です。7桁の数字ハイフンなしで入力してください(例:1000001)。」

2.2 重複伝達(色だけに頼らない)

  • テキスト+アイコン+コントラスト(本文4.5:1/非テキスト3:1)。
  • 形・位置でも伝達(入力欄の境界強調、フォーム上部の要約)。
  • 音や振動は任意、ミュートでも成立する表現を基本に。

2.3 2段構え(要約+個別)

  • ページ上部にエラー要約(各項目へのアンカーリンク)。
  • 各フィールド横に個別メッセージ視線の往復を最小化。

3. 予防設計:そもそもエラーを起こさない

  • 可視ラベル例示を近接配置(aria-describedbyで結び、読み上げにも露出)。
  • 型(type)・autocompleteinputmode で“打たせない”。
  • 制約は事前に:桁数・形式・選択条件はヒントで先出し。
  • 分割入力(住所・電話)は自然な順序に。
  • リアルタイム検証フォーカスアウトまたは入力の一時停止後(300–600ms)。途中の赤点灯は疲労の原因ですわ。

サンプル(ヒント+連係)

<div class="field">
  <label for="zip">郵便番号 <span aria-hidden="true">*</span></label>
  <input id="zip" name="zip" inputmode="numeric" autocomplete="postal-code"
         aria-describedby="zip-hint zip-err" required>
  <small id="zip-hint">7桁の数字。ハイフン不要(例:1000001)</small>
  <span id="zip-err" class="error" role="alert" hidden>7桁の数字で入力してください。</span>
</div>

4. エラーの視覚設計:見落とさせない、騒がせすぎない

  • :本文4.5:1、枠線やアイコンは3:1以上。
  • アイコン:形状で意味がわかるもの(例:エラー▲/注意!/成功✔)。
  • フォーカス:focus-visible太い輪郭+オフセットで所在を明確に。
  • 密度:同時に複数の赤が灯ると負荷大。要約で集約→個別へ誘導
  • モーション:揺らす・点滅は原則禁止。色+文で落ち着いて伝達。
.error { color:#b00020; }
input[aria-invalid="true"] { border:2px solid #c62828; box-shadow:0 0 0 3px rgba(198,40,40,.18); }
:focus-visible { outline:3px solid #ff9900; outline-offset:3px; }

5. ARIAとライブリージョン:通知の“聞こえ方”を整える

  • role="alert":即時・割り込み。エラーや重要失敗に限定。
  • role="status":静かな通知(保存完了・下書き保存など)。
  • aria-live="polite":自動更新の“控えめ”実況。
  • aria-atomic="true":部分更新でも全文読み直すべき時に。

サンプル(要約エラー+フォーカス受け皿)

<div id="error-summary" role="alert" aria-labelledby="err-title" hidden tabindex="-1">
  <h2 id="err-title">入力内容を確認してください</h2>
  <ul>
    <li><a href="#zip">郵便番号:7桁の数字で入力</a></li>
    <li><a href="#email">メール:形式が正しくありません</a></li>
  </ul>
</div>
<script>
function showSummary(){ const sum = document.getElementById('error-summary'); sum.hidden = false; sum.focus(); }
</script>

使い分けのコツ

  • フィールドエラー:フィールド脇に role="alert" を置くと確実に気づけます。
  • 保存成功role="status" で“静かに”知らせます。
  • ネットワーク切断alert回復手段(再試行/オフライン下書き)を同時に提示。

6. 文案の作り方:やさしく、短く、具体的に

6.1 文体の原則

  • 主体はユーザー:「あなた」ではなく項目名を主語に(「郵便番号が未入力です」)。
  • 禁止ではなく提案:「入力できません」は避け、「7桁の数字で入力してください」と行動を示す。
  • 専門用語の翻訳:タイムアウト→「一定時間操作がなかったため、セキュリティ上ログアウトしました」。
  • 数字で具体化:「しばらく」より「2分」。

6.2 よく使うテンプレ(日本語)

  • 未入力:「{項目}が未入力です。{要件}を入力してください。」
  • 形式不一致:「{項目}の形式が正しくありません。{例}の形式で入力してください。」
  • 範囲外:「{項目}は{最小}〜{最大}{単位}で入力してください。」
  • 重複:「この{項目}はすでに使用されています。別の{項目}をご検討ください。」
  • ネットワーク:「通信に失敗しました。接続を確認して再試行してください。下書きは保存済みです。」
  • 権限/セキュリティ:「この操作を行う権限がありません。管理者に連絡してください。」

6.3 “悪い例→良い例”

  • :「無効な入力です」 → :「電話番号ハイフンなしの10〜11桁で入力してください(例:0312345678)。」
  • :「エラーが発生しました(-1001)」 → :「通信がタイムアウトしました。接続を確認して再試行してください。」

7. 非同期・サーバーサイドの失敗:フォーム外の“現実”に備える

7.1 代表的なシナリオ

  • ネットワーク不安定:送信失敗・読み込み中断。
  • サーバーエラー:5xx、メンテナンス。
  • 競合:他デバイスでの同時編集。
  • 権限・認可:トークン失効、アクセス拒否。
  • ファイル:サイズ上限・拡張子・ウイルス検出。

7.2 回復戦略

  • 再試行(ボタン+ショートカット)を明示し、何度試せるかを一言で。
  • 下書き保存自動復元を提供。
  • 問い合わせ窓口(メール・電話・テキスト中継)をテキストで提示。
  • 状態の可視化role="status" で「送信中…」「保存しました」を短く。

サンプル(再試行UI)

<div role="alert">
  保存に失敗しました。ネットワークを確認して<a href="#" id="retry">再試行</a>してください。下書きは保持されています。
</div>
<script>
document.getElementById('retry').addEventListener('click', e => { e.preventDefault(); saveDraftAgain(); });
</script>

8. 認知負荷を下げる:順序、段階化、選択肢の“絞り込み”

  • 段階的開示:一度に出しすぎない(アコーディオン・ステップ)。
  • 選択肢は5〜7個程度に。多い場合は検索つきコンボへ。
  • 例示は具体的に(“東京→千代田区→1-1-1”のように階段)。
  • 長文の要約:先頭に「要点:」を置く。
  • アイコンは補助:必ずテキストが主役

9. 多言語・読み上げ・音声操作:言語と入出力の多様性に寄り添う

  • lang 属性をページと一部の外来語に正確に付与。
  • 可視文言=アクセシブルネーム(2.5.3)。アイコンボタンには同じ語を。
  • 機械翻訳でも崩れない短文・構文に(主語・述語を簡潔に)。
  • 数字・日付・通貨ローカライズ(例:YYYY-MM-DD を明記)。
  • 音声操作のため、ボタン名・リンク文を行為中心に(「削除」「送信」「やり直す」)。

10. コード雛形:フォーム+要約エラー+個別エラー(コピペOK)

<form id="f" novalidate aria-describedby="note">
  <p id="note">*は必須。入力は2分ほどです。</p>

  <div id="summary" role="alert" aria-labelledby="summary-title" hidden tabindex="-1">
    <h2 id="summary-title">入力内容を確認してください</h2>
    <ul id="summary-list"></ul>
  </div>

  <div class="field">
    <label for="name">氏名 <span aria-hidden="true">*</span></label>
    <input id="name" name="name" required aria-describedby="name-err">
    <span id="name-err" class="error" role="alert" hidden>氏名は必須です。</span>
  </div>

  <div class="field">
    <label for="email">メール <span aria-hidden="true">*</span></label>
    <input id="email" name="email" type="email" required aria-describedby="email-hint email-err">
    <small id="email-hint">例:user@example.com</small>
    <span id="email-err" class="error" role="alert" hidden>メールの形式で入力してください。</span>
  </div>

  <button id="send">送信</button>
  <div id="status" role="status" aria-atomic="true" class="sr-only"></div>
</form>

<script>
const fields = [
  { id:'name', err:'name-err', check: el => el.value.trim().length>0, msg:'氏名は必須です。' },
  { id:'email', err:'email-err', check: el => el.validity.valid, msg:'メールの形式で入力してください。' }
];

document.getElementById('f').addEventListener('submit', e=>{
  e.preventDefault();
  const list = document.getElementById('summary-list');
  const sum  = document.getElementById('summary');
  list.innerHTML = '';
  let firstBad = null;

  fields.forEach(f=>{
    const el  = document.getElementById(f.id);
    const ok  = f.check(el);
    const err = document.getElementById(f.err);
    el.setAttribute('aria-invalid', String(!ok));
    err.hidden = ok;
    if(!ok){
      if(!firstBad) firstBad = el;
      list.insertAdjacentHTML('beforeend', `<li><a href="#${f.id}">${f.msg}</a></li>`);
    }
  });

  if(firstBad){
    sum.hidden = false; sum.focus();
    list.querySelectorAll('a').forEach(a=> a.addEventListener('click', ()=>document.getElementById(a.getAttribute('href').slice(1)).focus()));
    return;
  }

  const st = document.getElementById('status');
  st.textContent = '送信中です…';
  document.getElementById('send').disabled = true;
  setTimeout(()=>{ // 擬似送信
    st.textContent = '送信が完了しました。ありがとうございました。';
    document.getElementById('send').disabled = false;
    e.target.reset();
  }, 1000);
});
</script>

11. “通知”のアクセシビリティ:トースト・バナー・インラインの使い分け

  • トースト:短命・軽量な成功通知(保存完了など)。履歴を持てると安心。
  • バナー:ページ上部で広域の警告(システム障害・メンテ情報)。
  • インライン:特定エリアの結果(フィルタのヒット数・フォームの個別エラー)。

原則

  • 自動で消える通知は読み切れる時間(3–5秒+フォーカス時は保持)。
  • 一時停止/再開の制御があると親切。
  • role="status" を基本、重要度が高いもののみ alert

12. 失敗しないレビュー観点(デザイン/文案/実装 共通)

  1. 観点:What/Where/How が1メッセージに入っている?
  2. 重複伝達(テキスト+色+アイコン)で色依存していない?
  3. 可視ラベル=アクセシブルネーム(2.5.3)になっている?
  4. 要約エラー→個別エラーの導線があり、キーボードで往復できる?
  5. フォーカスは見失わない?:focus-visible が十分太い?
  6. ライブリージョンの使い分けは適切?(alert乱用していない)
  7. リアルタイム検証控えめで、入力途中に赤が点かない?
  8. ネットワーク失敗再試行・下書き・連絡先がある?
  9. モバイル(320px)で崩れず、ターゲットサイズ44–48px?
  10. 多言語でも破綻しない短文構文?固有名詞・単位・日付は一貫?

13. 5分スモークテスト:毎リリースに回せる最小儀式

  • Tabだけで入力→送信→要約→個別へジャンプ→修正→再送信が完了。
  • スクリーンリーダー(NVDA/VoiceOver)で、エラー発生時に読み上げが即時に行われる。
  • 色をグレースケールにしても、テキストとアイコンで意味が変わらない。
  • オフラインにして送信→再試行が提示され、下書きが残る。
  • 文字拡大(150%)でも折返し破綻なし、重要情報が折りたたまれない。

14. ケーススタディ:離脱率を下げた“3つの変更”

Before

  • プレースホルダーのみでラベル無し。
  • 入力途中で即赤エラー・常時トースト。
  • 送信失敗は「Error -1001」のみ。

After

  1. 可視ラベル+例示を近接、aria-describedbyで連係。
  2. リアルタイム検証はフォーカスアウト時へ変更、要約+個別の二段構えに。
  3. ネットワーク失敗に再試行ボタン下書き保存を追加。
    結果:フォーム完了率 +18%、エラー由来のCS問い合わせ −37%、送信失敗時の離脱 −52%

15. よくある落とし穴と回避策

落とし穴 何が起きる? 回避策
「無効です」だけの曖昧文 直せない・不安 What/Where/How の三点セット
色だけの強調 見落とし・誤認 テキスト+アイコン+コントラスト
フィールド毎にrole="alert"乱立 騒がしい・読み上げ渋滞 重要だけalert、他はstatus
入力途中の赤連発 認知負荷↑・離脱 フォーカスアウト時/遅延検証
要約なし どこを直すか迷子 要約にアンカー→個別へ
専門語・略語の濫用 意味不明 平易化+注釈(abbr等)
自動で消える通知 読み逃し 一時停止/履歴/フォーカス保持
エラー番号のみ CS負担↑ 人間語+番号(開示は末尾)

16. 組織導入:言語スタイルガイドとデザインシステム

  • 言語スタイルガイド
    • 人称・敬体、「〜してください」統一。
    • 禁止語(抽象語・脅し文句)と推奨表現の対照表。
    • テンプレ(未入力/形式/範囲/重複/権限/ネットワーク)。
  • デザインシステム
    • コンポーネント(アラート/トースト/バナー/エラーフィールド)の名前・役割・値(NRV)を明文化。
    • 色・コントラスト・アイコンの最小比、:focus-visibleの太さ。
    • ライブリージョンの運用規約alertの濫用防止)。
  • 運用
    • PRテンプレにa11yチェック項目を組み込み、自動検査+5分スモークを定例化。
    • CSの問い合わせログを言い回しの改善へ反映。

17. 誰がどう助かる?(具体的インパクト)

  • 視覚に多様性のある方:色だけに頼らない重複伝達/高コントラストで見落としが減少
  • スクリーンリーダー利用者alertstatusの適切な通知と要約→個別の導線で修正が短時間に。
  • 認知・学習特性の多様な方:短文・具体・段階化で負荷が低減
  • モバイル・片手操作:ターゲットサイズ確保・リアルタイム検証の抑制で誤タップ・誤判定が減少
  • 回線が不安定な環境再試行/下書き保存作業の中断を回避
  • CS・運用側:問い合わせの定型化・減少、対応の平均時間短縮

18. アクセシビリティレベルと到達点

  • WCAG 2.1 AA 主対応
    • 1.3.1 情報及び関係性(要約+個別、関連付け)
    • 1.4.1 色の使用(色依存の回避/重複伝達)
    • 1.4.3 / 1.4.11 コントラスト(テキスト/非テキスト)
    • 2.1.1 キーボード(要約→個別への移動)
    • 2.2.2 一時停止・停止・非表示(通知の制御)
    • 2.4.3 / 2.4.6 / 2.4.7 フォーカス順序・ラベル・フォーカス可視
    • 3.3.1 / 3.3.2 / 3.3.3 エラーの特定・ラベルまたは説明・エラーの提案
    • 4.1.2 名前・役割・値(alert/status/aria-invalid 等)
  • AAAでの発展(推奨)
    • 1.2.8(メディアの代替:トラブルシュート動画にトランスクリプト)
    • 1.4.6(コントラスト強化)
    • 3.3.6(エラーの予防:重要取引の確認ダイアログ強化)

19. まとめ:やさしい言葉は、だれの心にも届く

  1. What/Where/How の三点セットで“すぐ直せる”メッセージに。
  2. 要約+個別フォーカス移動で修正導線を最短化。
  3. 重複伝達(テキスト+アイコン+コントラスト)で色依存を脱却。
  4. リアルタイム検証は控えめに、予防的マイクロコピーでエラーを減らす。
  5. alert/statusの使い分けと通知の静けさを守る。
  6. 再試行・下書き・連絡先など、回復手段を必ず添える。
  7. 言語スタイルガイドデザインシステムで、チームの言葉とふるまいをそろえる。

エラーメッセージは、叱責ではなく伴走です。
あなたのプロダクトが、つまずいた瞬間にこそやさしく確かな手を差し伸べられるよう、わたしも心を込めてお手伝いしますね。


投稿者 greeden

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)