トピックを検索
名前がない、または読まれてしまうSVGアイコン
注文一覧は各注文の状況を名前のないインラインSVGだけで示し、見出しの飾りのアイコンは title 要素のファイル名が読み上げられます。
問題
スクリーンリーダー利用者が、注文が届いたかどうかを知ることができず、代わりにアイコンのファイル名を聞かされます。
オンラインショップのアカウントページに「ご注文履歴」という見出しがあり、その前に小さな箱のアイコンがあります。その下に注文が3件並び、各行には注文番号と日付があり、行の最後に色の付いたアイコンがあります。緑のチェック、青のトラック、赤い感嘆符の円です。見える人は、1件は届き、1件は配送中で、1件は支払いに失敗したと一目で分かります。スクリーンリーダーは「icon-package ご注文履歴、見出し」と読み、続けて「注文1042、10月3日、画像」「注文1043、10月6日、画像」「注文1044、10月8日、画像」と読みます。アイコンでは何も読まないスクリーンリーダーもあります。この一覧で一番大事な状況が、聞いている人に届きません。
アイコンはすべて同じアイコンセットのもので、どれも <svg> としてインラインで埋め込まれています。状況のアイコンには、画像として扱われるように role="img" が付いていますが、名前がないため、何も伝えない画像として読まれます。箱のアイコンは何かを伝えるためのものではありませんが、アイコンセットがすべてのSVGに <title>icon-package</title> を入れており、見出しは title を含む中身から名前を作ります。そのため、黙っているべきアイコンが読まれ、伝えるべきアイコンが黙っています。どちらも1.1.1を満たしません。意味のある非テキストコンテンツには代替テキストが必要で、飾りは支援技術から隠す必要があります。
状況のアイコンには色も付いていますが、ここでの問題は色ではありません。アイコンはそれぞれ形が違います。問題は、形も色もテキストとしては存在しないことです。
10グループ中2グループに影響
- 全盲 (影響あり)
- 弱視 (影響なし)
- 色覚 (影響なし)
- ろう (影響なし)
- 難聴 (影響なし)
- 発話 (影響なし)
- 手の操作 (影響なし)
- 届く範囲・力 (影響なし)
- 認知 (影響あり)
- 光過敏 (影響なし)
- 視覚を使わない スクリーンリーダー利用者には、状況の場所で「画像」とだけ読まれるか何も読まれず、配達済みの注文と支払いに失敗した注文を区別できません。見出しの前には、アイコンのファイル名も聞こえます。
- 言語・認知・学習の能力が限られる トラックや感嘆符の入った円が何を表すか分からない人は、状況が言葉で書かれていないと、アイコンだけを頼りにするしかありません。
axe の svg-img-alt と role-img-alt は、role="img" で名前のないSVGを検出するため、状況のアイコンは見つかります。ただし、ロールのないSVGは検出しません。そうしたSVGは、ブラウザーによって飛ばされたり、グループとして伝えられたりします。箱のアイコンも検出されません。名前のある見出しの中にあるため問題がないように見えますが、実際には「icon-package」が読まれています。AIによる手早い修正では、ファイル名のとおり形で名前を付けたり(「チェック」「トラック」「警告」)、警告を消すためにすべてのアイコンを隠して状況そのものを消したりしがちです。この一覧で各アイコンが何を意味するかを知る人にしか、名前が必要か、どんな名前にするかは判断できません。
試してみる
見えている内容と、スクリーンリーダーの読み上げを比べてください。
下の欄に、スクリーンリーダーの読み上げが上から順に出ます。どの注文が届き、どの支払いが失敗したか分かりますか?
問題あり 直してみませんか?
ご注文履歴
- 注文1042 10月3日
- 注文1043 10月6日
- 注文1044 10月8日
スクリーンリーダーの読み上げ:
- icon-package ご注文履歴、見出し
- リスト、3項目
- 注文1042、10月3日、画像
- 注文1043、10月6日、画像
- 注文1044、10月8日、画像
再現デモです。「問題あり」は意図的にアクセシブルでない状態にしています。
修正方法
意味のあるSVGにはすべて名前を付け、意味のないSVGはすべて aria-hidden="true" で隠します。
- 1インラインSVGは、名前を付けるか隠すかのどちらかにし、どちらでもない状態にしない。
- 2形ではなく、ここでのアイコンの意味を、aria-label か、隠したアイコンの隣の見えるテキストで伝える。
- 3飾りのアイコンは aria-hidden="true" で隠し、付いてきた title を取り除く。
これだけでは不十分です。 スクリーンリーダー利用者には1.1.1を満たしますが、画面上の状況はアイコンのままです。トラックや感嘆符の意味が分からない見える人は、推測するしかありません。
<h2> <svg viewBox="0 0 24 24"><title>icon-package</title>…</svg> ご注文履歴</h2><ul class="orders"> <li> 注文1042 <span class="date">10月3日</span> <svg role="img" viewBox="0 0 24 24" class="ok">…</svg> </li> <li> 注文1043 <span class="date">10月6日</span> <svg role="img" viewBox="0 0 24 24" class="info">…</svg> </li> <li> 注文1044 <span class="date">10月8日</span> <svg role="img" viewBox="0 0 24 24" class="error">…</svg> </li></ul>状況のアイコンは代替テキストのない画像で、状況が失われます。箱のアイコンは何も加えないのに、その title が見出しの一部として読まれます。
状況のアイコンは role="img" のままで一つの画像として伝わり、その注文にとっての意味を表す aria-label が加わります。スクリーンリーダーは「注文1042、10月3日、配達済み、画像」と読みます。箱のアイコンは title を外して aria-hidden="true" にするため、見出しは「ご注文履歴」と読まれます。見た目は修正前とまったく同じで、それがこの方法の限界です。状況はスクリーンリーダーには言葉で届きますが、画面上はアイコンのままです。トラックが「配送中」を表すと知らない人や、赤い円を支払いではなくサイトのエラーと受け取る人は、推測するしかありません。AやAAの達成基準は言葉を見えるように書くことを求めていませんが、認知障害のある人のためのW3Cのガイダンスは、アイコンにテキストを添えることを求めています。
どちらの方法でも、各状況に代替テキストがあり、飾りのアイコンは読まれないため、1.1.1を満たします。アイコンに名前を付ける方法は属性を変えるだけでデザインはそのままですが、その言葉は支援技術にしか届きません。aria-label を翻訳しない翻訳ツールもあり、見える人は各アイコンの意味を知っている必要があります。状況をテキストで書く方法は普通のHTMLで済み、ページを読むすべての人に伝わり、ARIAに任せるものが残りません。必要なのは行の余白だけです。こちらを使ってください。名前を付けたアイコンは、情報の詰まった表など、言葉を置く余白が本当にない場所に限り、利用者がすでに知っているアイコンだけにして、近くに見える凡例を置きます。
名前を付けるか隠すか、どちらかにする。 ロールも aria-hidden もないインラインSVGの扱いは、ブラウザーとスクリーンリーダーによって違います。飛ばすもの、「グループ」や「画像」と読むもの、<title> や中のテキストを読むものがあります。すべてのアイコンについて決め、その判断は共通のアイコンコンポーネントで行います。label を受け取り、指定されたら role="img" と aria-label を付け、なければ aria-hidden="true" を付けるようにします。
アイコンセットの title。 多くのアイコンセットやデザインツールの書き出しは、すべてのSVGにファイル名の <title> を入れます。取り除くか、意味を表す言葉に書き換えます。<title> でもSVGに名前を付けられます(role="img" と、それを指す aria-labelledby)。ただし、ブラウザーによってはツールチップとして表示され、隠したアイコンに残った title は何の役にも立たないため、aria-label のほうが簡単です。
img やCSSで読み込むSVG。 <img src="tick.svg"> で表示したアイコンは画像の決まりに従い、alt="配達済み" か alt="" にします。CSSの背景やマスクで描いたアイコンは支援技術から見えないため、意味はテキストに書きます。::before で入れるアイコンフォントは意味のない文字として読まれることがあるため、aria-hidden="true" の要素に入れます。
ボタンやリンクの中のアイコン。 ボタンやリンクの唯一の中身がアイコンの場合、アイコンはそのコントロールの名前の一部です。名前はコントロールに付け、アイコンは隠します。アイコンだけのボタンのガイドを参照してください。
コントラストと強制カラー。 意味のあるアイコンには、1.4.11により背景との3:1のコントラストが必要です。fill="currentColor" か stroke="currentColor" で描くと、強制カラーモードでも文字の色に合わせて表示され、消えません。
focusable="false"。 古いInternet ExplorerはすべてのSVGをタブ順に入れていたため、今も focusable="false" を付けるアイコンセットが多くあります。付いていても害はありませんが、もう必要ありません。
AI コーディングアシスタントで修正しますか? このガイドを Markdown で取得
修正の確認
マウスを使わない4つの確認
確認方法: スクリーンリーダー、強制配色
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。アイコンセットや共通のアイコンコンポーネントを変更した際は、再度確認します。
制限
このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。パス、クラス名、SVGの中の … は仮のものです。名前の付いたSVGの読み上げ方はスクリーンリーダーによって少しずつ違い、名前のないSVGを読むものもあるため、利用者が使う支援技術で確認してください。アイコンが飾りかどうかは周りのテキストがすでに何を伝えているかで決まり、ページを知る人にしか判断できません。実際に使用する支援技術で、操作全体を確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
コードを更新しても、使いやすさを保つために
ガイドの内容を、コーディングエージェントやCIで使える開発ルールにまとめます。更新後は、キーボードとスクリーンリーダーで再テストし、問題が再発していないか確認します。