トピックを検索
「ボタン」としか読まれない顔アイコンの評価
おすすめの感想を5つの顔で尋ねるカードで、各顔はボタンですが、中身は支援技術から隠した絵だけで、titleも空です。そのため、どの顔も「ボタン」とだけ読み上げられ、両端の下にある「とても悪い」「とても良い」も、どの顔とも結び付いていません。
<button><svg aria-hidden="true"> 問題
スクリーンリーダーの利用者には名前のないボタンが5つ聞こえるだけで、どの顔が何を意味するのか分からず、音声操作の利用者は顔を名前で押せません。そのため回答できないか、意図しない回答を送ってしまいます。
あるレシピサイトに、おすすめのレシピが表示され、その下の小さなカードが「このおすすめはいかがですか?」と尋ねています。しかめ面から満面の笑みまで、丸い顔が5つ並び、最初の顔の下に「とても悪い」、最後の顔の下に「とても良い」と書かれています。顔ならフォームより気軽に答えられ、ページの隅にも収まります。顔をクリックすると回答が送られます。
スクリーンリーダーを有効にして、Tabでカードに入ります。読み上げは「ボタン」、また「ボタン」と、顔ごとに5回続きます。どの顔が何を表すのかも、どちらの端が良いのかも伝わりません。カードを先頭から読むと、「このおすすめはいかがですか?」の後に「ボタン」が5回続きます。「とても悪い」「とても良い」は、すべてのボタンの後でようやく2行のテキストとして読まれ、どちらの端の顔にも結び付いていません。音声操作の利用者が「とても良いをクリック」と言っても、その名前のボタンはないので何も起きません。
各顔は本物の button なので、Tabで届き、Enterキーで押せます。欠けているのは名前です。ブラウザーはボタンの名前を、aria-labelledby、aria-label、ボタンに結び付いた label、ボタン内のテキストの順に探し、最後の手段として title を使います。ここでボタンの中にあるのは aria-hidden="true" で隠した顔の絵だけで、title は付いていても空です。どこからも名前が得られず、ボタンは役割だけで読み上げられます。空の title からは、共通のアイコンボタンのコンポーネントが使われていることがうかがえます。名前を入れる場所はあるのに、このカードでは空のままです。
このため、3つの達成基準を満たしていません。4.1.2 名前・役割・値:各顔は役割はあっても名前のない操作部品で、押すと何が起きるかをソフトウェアが伝えられません。WCAGはこれを失敗例F68として挙げています。1.1.1 非テキストコンテンツ:顔は回答そのものを表す絵で、操作部品として働く絵には、目的を伝える代替テキストが必要です。ここでは「悪い」「ふつう」「良い」の違いは、口の形で描き分けてあるだけです。1.3.1 情報及び関係性:見た目では、上の設問が5つの顔にかかっていること、「とても悪い」が最初の顔の、「とても良い」が最後の顔の言葉であることが分かります。ところがコードでは、設問はどこにも結び付かない div で、顔はその下にまとめられておらず、2つの言葉はすべてのボタンの後ろにある別の div に入っています。そのため最後に、どの顔にも属さないまま読まれます。
短い感想のカードは、動画の後、サポートのチャットの後、おすすめの後など、何かの終わりに出てきます。顔に名前がないと、見えない人は質問を飛ばすか、当てずっぽうで顔を押すことになります。その人たちの回答は、抜け落ちるか当て推量になり、顔の意味どおりの回答は、顔が見える人からしか集まりません。
10グループ中2グループに影響
axeは各顔を button-name として報告します。中身が aria-hidden で隠されたものだけで、title も空のボタンには名前がないからです。EaseWebの診断もaxeを実行し、5つの顔を axe:button-name として報告します。自動チェックで分かるのはここまでです。名前が値を伝えているかは判断できず、aria-label="しかめ面"、アイコンのファイル名の "face-2"、"1" でも合格になります。設問がどこにも結び付いていないことや、両端の言葉がボタンの後ろに取り残されていることも分かりません。指摘を直すように頼むと、コード生成AIは、顔に絵の説明で名前を付けたり、ボタンではなく隠した svg に aria-label を付けたりすることがあります。後者では、隠した要素は名前に何も加えないため、ボタンは名前のないままです。また、下の言葉から両端の2つだけに名前を付け、中央の3つを空のまま残すこともあります。スクリーンリーダーでTabを押して顔を移動し、それぞれが値を読み上げるか確かめてください。
試してみる
Tabで顔を順に移動し、それぞれが何と読み上げられるか確かめてください。
下の欄に、顔にフォーカスが移ったときの読み上げと、カードを先頭から読んだときの読み上げが出ます。「とても良い」はどの顔で、その言葉はどこで読まれるでしょうか?
問題あり 修正できますか?
スクリーンリーダーの読み上げ:
(Tabで顔へ移動)
カードを先頭から読むと:
- このおすすめはいかがですか?
- ボタン
- ボタン
- ボタン
- ボタン
- ボタン
- とても悪い
- とても良い
修正方法
各顔に値を言葉で名前として付け、設問をグループの名前にします。
- 1すべての顔に、ボタン内のテキストで、値を言葉にした名前を付ける。
- 2顔は設問の下にまとめ、設問をfieldsetのlegendにする。
- 3顔の横に表示する言葉は、そのボタンの中に入れ、ボタンの名前にする。
<form class="survey" action="/feedback" method="post"> <div> <div class="question">このおすすめはいかがですか?</div> <div class="faces"> <button class="face" name="answer" value="1" title=""> <svg aria-hidden="true"> <use href="#face-very-bad"></use> </svg> </button> <button class="face" name="answer" value="2" title=""> <svg aria-hidden="true"> <use href="#face-bad"></use> </svg> </button> <button class="face" name="answer" value="3" title=""> <svg aria-hidden="true"> <use href="#face-okay"></use> </svg> </button> <button class="face" name="answer" value="4" title=""> <svg aria-hidden="true"> <use href="#face-good"></use> </svg> </button> <button class="face" name="answer" value="5" title=""> <svg aria-hidden="true"> <use href="#face-very-good"></use> </svg> </button> </div> <div class="ends"> <div>とても悪い</div> <div>とても良い</div> </div> </div></form>デザインはそのままに、値をボタンに入れる
<form class="survey" action="/feedback" method="post"> <fieldset> <legend class="question">このおすすめはいかがですか?</legend> <div class="faces"> <button class="face" name="answer" value="1"> <svg aria-hidden="true"> <use href="#face-very-bad"></use> </svg> <span class="end">とても悪い</span> </button> <button class="face" name="answer" value="2"> <svg aria-hidden="true"> <use href="#face-bad"></use> </svg> <span class="visually-hidden">悪い</span> </button> <button class="face" name="answer" value="3"> <svg aria-hidden="true"> <use href="#face-okay"></use> </svg> <span class="visually-hidden">ふつう</span> </button> <button class="face" name="answer" value="4"> <svg aria-hidden="true"> <use href="#face-good"></use> </svg> <span class="visually-hidden">良い</span> </button> <button class="face" name="answer" value="5"> <svg aria-hidden="true"> <use href="#face-very-good"></use> </svg> <span class="end">とても良い</span> </button> </div> </fieldset></form>各ボタンの中身は、支援技術から隠した絵と空の title だけなので、5つのどれにも名前がありません。設問と2つの言葉はボタンとは別の div で、どのボタンにも結び付いていません。画面の上では顔の列を挟んでいますが、コードの上では列の前後にあるただのテキストです。
カードの見た目はデザインどおりで、顔も、両端の下の2つの言葉も変わりません。各ボタンには値がテキストとして入ったので、スクリーンリーダーは「とても悪い、ボタン」から「とても良い、ボタン」まで読み上げ、音声操作ではその言葉を言えば顔が押されます。両端の言葉は、最初と最後のボタンの中へ移り、表示は今までどおりボタンの下です。画面の言葉がそのままボタンの名前になり、列の後ろで単独に読まれることもなくなります。中央の3つには、視覚的に隠したテキストで言葉を入れています。設問は顔を囲む fieldset の legend にしたので、スクリーンリーダーは通常、Tabでグループに入るときに「このおすすめはいかがですか?、グループ」のように名前を読み上げます。何の名前にもなっていなかった空の title は外しました。
どちらも3つの達成基準を満たします。値をボタンに入れる方法は、カードをデザインどおりに保てるので、デザインに広げる余地がない場合に向いています。すべての顔の下に言葉を書く方法は、普段の見た目が変わりますが、カードを読むすべての人に各顔の意味が伝わります。顔の表情を読み取りにくい人、拡大鏡で顔を一つずつ見ている人、このサイトで中央の顔が何を意味するのか迷う人にも伝わります。カードに余裕があるならこちらを選んでください。幅の狭いスマートフォンでは、「とても良い」が顔の下に収まるかをデザインファイルで確かめるか、2行で描いておきます。
この顔は押した瞬間に回答を送るので、ボタンにしています。一度押せば一つの回答が送られる、実際のカードと同じ動きです。尺度が、後でまとめて送る長いフォームの設問の一つである場合や、送る前に回答を変えられる場合は、ラジオボタンのグループとして作ってください。星の場合の作り方はキーボードでもスクリーンリーダーでも選べない星評価で示しています。顔も同じように、ラジオボタンの上に描けます。作り方によって、使うキーも変わります。ボタンの顔はTabで一つずつ移動し、EnterキーかSpaceキーでその回答を送ります。ラジオボタンのグループではTabが止まるのは一度だけで、矢印キーで選択が移ります。そのため、ラジオボタンのグループは選んだだけで送信してはいけません。矢印キーは通り過ぎる顔を次々にチェックするので、キーボードで「とても悪い」から「良い」へ移ろうとすると、最初の一押しで「とても悪い」が送られてしまいます。ラジオボタンのグループには、送信用のボタンが必要です。
空の title に言葉を入れても、各ボタンに名前は付きます。ほかに名前がないとき、ブラウザーは title を使うからです。これで4.1.2も満たします。ただし多くのブラウザーでは、ツールチップはマウスを顔の上に置いたときにしか出ないため、目の見える人でも、キーボードやタッチスクリーンで操作していれば言葉は見えません。コンポーネントがほかに何も受け付けない場合に限って使ってください。各ボタンに aria-label を付けても、隠したテキストと同じように名前が付きます。二つの違いは名前がないアイコンだけのボタンで比べています。どちらを使う場合も、付ける先はボタンです。aria-hidden="true" の付いた svg に aria-label を付けても無視されます。
fieldset は、入力欄だけでなくボタンもまとめられます。レイアウトの都合で使えない場合は、role="group" と、設問を指す aria-labelledby を持つ要素でも同じ役目を果たせます。顔の名前は、描いた順に悪いほうから良いほうへ付け、名前の並びを列の向きと揃えます。尺度の言葉はサイトが決めるものです。カードが「どのくらい役に立ちましたか?」と尋ねるなら、名前は両端の言葉に合わせて「役に立たなかった」から「とても役に立った」のようにします。
AI コーディングアシスタントで修正しますか? このガイドを Markdown で取得、または全ガイドをコーディングエージェントで使う。
デザインの案
顔でも、ピル型でも、親指でも、答えごとに言葉があれば描けます。
短い感想の質問の描き方を4通り並べました。Tabで試してください。3つはどの答えにも言葉があり、残る1つは、スクリーンリーダーが絵そのものを読み上げます。
デザインファイルで
- すべての顔に言葉を書く。画面に出すのが両端だけでも、「とても悪い」から「とても良い」まで書いておく。スクリーンリーダーと音声操作はその言葉を使う。
- 答えの上に設問を書き、グループの名前にする。
- フォーカスの枠が付いた答えを描く。送る前に選び直せるなら、選んだ状態の答えも描く。
- スマートフォンの幅で列を描き、表示する言葉がすべて収まるようにする。
合格
- 選んだ顔の言葉が下に出る表情の列 とても悪いからとても良いまでの5つの顔に、それぞれの意味で名前を付け、選んだ顔の言葉を列の下に書きます。顔の表情を読み取れなくても伝わります。フォームを送るまでは選び直せます。選んだ顔には淡い琥珀色と、#b45309の輪(白に対して5.02:1)が付きます。
- 顔と言葉を並べたピル型のボタン 小さな顔と言葉を横に並べた、角の丸いピル型のボタンを5つ置きます。スマートフォンでは2行に折り返します。押すと回答が送られます。言葉がそのままボタンの名前になり、#6b7280の枠線(白に対して4.83:1)がボタンの縁を示します。
- 言葉を添えた2つの親指 答えが2つで足りるなら、下向きの親指に「好みではない」、上向きの親指に「良いおすすめ」を添えた、枠線付きのボタンにします。意味は言葉が伝えるので、親指の向きを読み取る必要はありません。
不合格
- 絵文字だけのボタンWCAG 1.1.1 😠から😄までの5つの絵文字は親しみやすく、アイコンも要りません。ただし各ボタンの名前は絵文字自体の名前になり、絵の説明であって、表す回答ではありません。
修正の確認
マウスを使わない4つの確認
確認方法: スクリーンリーダー、音声入力、キーボード、タッチ
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。カードやアイコンのコンポーネントを変更した際は、再度確認します。
制限
このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。CSSは最小限の例なので、顔の大きさ、顔の間隔、フォーカスの枠を実際のデザインで確認してください。このようなカードには、名前のない×印の閉じるボタンが付いていることもあります。それは名前がないアイコンだけのボタンで扱う問題です。回答後に顔と入れ替わるお礼の言葉が読み上げられるかは、画面に出ても読み上げられないステータスメッセージで扱います。赤、黄、緑の丸のように、色だけで見分ける顔は別の問題で、色だけに頼る表示のトピックで扱います。そのガイドは準備中です。カード全体を、スクリーンリーダー、音声操作、スマートフォンで確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
参考資料
コードを更新しても、使いやすさを保つために
ガイドの内容を、コーディングエージェントやCIで使える開発ルールにまとめます。更新後は、キーボードとスクリーンリーダーで再テストし、問題が再発していないか確認します。