トピックを検索
選んだ条件も一覧の変化も伝わらない絞り込みリンク
商品一覧の上のカテゴリーリンクは、押すとページを読み込まずに一覧だけを描き替え、選んだリンクもクラスで塗りつぶすだけなので、スクリーンリーダーには一覧の変化も選んだ条件も伝わらない
link.classList.add('is-active'); 問題
スクリーンリーダーの利用者が絞り込みを押しても何も聞こえず、一覧が変わったことも、どれを選んだかも分からない
あるショップのテーブルウェアのページでは、6点の商品の上に、「すべて」「マグ」「皿」「ボウル」の丸いリンクが横に並んでいます。どれも自分のアドレスを持つ本物のリンクなので、新しいタブで開いたり、人に送ったりできます。ところが、スクリプトがページの読み込みを止めています。「マグ」を押すと、マグの商品を取得して下の一覧を描き替え、アドレスを ?category=mugs に変え、「マグ」を黒く塗りつぶします。画面が見える人には、塗りつぶされたリンクと、マグ2点に減った一覧が見えます。スクリーンリーダーの利用者は「マグ、リンク」と聞いてEnterキーを押しますが、何も聞こえません。新しいページは読み込まれないので新しいタイトルは読まれず、スクリプトも何も伝えません。リンクへ戻っても、聞こえるのは前と同じ「マグ、リンク」で、ほかのリンクも同じように読まれます。商品を順にたどらない限り、一覧が変わったことも、どの絞り込みが効いているのかも分かりません。
それぞれのリンクは、絞り込みを選ぶためのコントロールです。塗りつぶされたリンクは「この条件が効いている」という状態を示しています。達成基準4.1.2「名前(name)・役割(role)及び値(value)」は、利用者が設定できる状態を支援技術が取得できること、そしてその変化が支援技術に通知されることを求めています。ここでは、その状態を表すのがスタイルシートだけが読む is-active クラスなので、押す前も押したあとも、支援技術に伝えられる状態がありません。さらにスクリプトは、本来はページの読み込みが担う、内容とアドレスの入れ替えを引き受けながら、読み込みなら何もしなくても起きる読み上げを省いています。リンクは「どこかへ移動する」と伝えているのに、実際にはその場でページを変え、今どこにいるのかを伝えるものが何も返ってきません。
こうした絞り込みの行は、商品の一覧、記事の一覧、検索結果の上に置かれます。スマートフォンでは横にスクロールする1行になり、変わる一覧は画面の外にあることが多いため、行だけを見ている人には、リンクが塗りつぶされたことしか分かりません。
10グループ中2グループに影響
スキャンは、名前とアドレスを持つ4つの正しいリンクと見なし、問題なしとします。リンクを押さないため、ページがその場で変わることに気づかず、is-active、selected、current といったクラス名にも意味を読み取りません。EaseWebの診断は、アドレスが表示中のページで、同じ行のほかのリンクと見た目が違うのに、コードには選択中の目印がないリンクを指摘します。そのうえで、絞り込みリンクの行を一つずつ目視確認に回します。何が読まれるかは、押してみないと分からないからです。AIアシスタントに絞り込みリンクの修正を頼むと、タブやリストボックスのための aria-selected や role="tab" を付けることがあります。リンクをボタンに変えてしまい、新しいタブで開いたり共有したりするためのアドレスがなくなることもあります。商品の一覧に aria-live を付ける例もありますが、押すたびに全商品が読み上げられるか、一覧ごと置き換わると何も読まれなくなります。
試してみる
絞り込みを選んで、何が読み上げられるか聞いてみましょう
Tabキーで「マグ」まで移動し、Enterキーを押します。下の欄に、スクリーンリーダーの読み上げが出ます。押したあとは、もう一度Tabキーで絞り込みをたどってください。選んだものが「現在のページ」と読まれるか、変化が読まれるかを確かめます。
修正方法
選んだ絞り込みを示し、今の表示内容を伝える
<title>マグ | テーブルウェア</title>…<ul class="filters"> <li> <a href="/shop">すべて</a> </li> <li> <a href="/shop?category=mugs" class="is-active">マグ</a> </li> <li> <a href="/shop?category=plates">皿</a> </li> <li> <a href="/shop?category=bowls">ボウル</a> </li></ul><ul id="products">…</ul>問題点2点
is-activeクラスは「マグ」を塗りつぶすだけです。スクリーンリーダーは、ほかの3つと同じく「マグ、リンク」と読みます。- スクリプトがページの読み込みを止めて一覧をその場で描き替えるため、押したあとに何も読まれません。新しいページのタイトルも、メッセージもありません。
選んだリンクに目印を付け、変化を伝える
<title>マグ | テーブルウェア</title>…<ul class="filters"> <li> <a href="/shop">すべて</a> </li> <li> <a href="/shop?category=mugs" aria-current="page">マグ</a> </li> <li> <a href="/shop?category=plates">皿</a> </li> <li> <a href="/shop?category=bowls">ボウル</a> </li></ul><p id="filter-status" role="status" class="visually-hidden"></p><ul id="products">…</ul>修正の手順5ステップ
- サーバーが返すマークアップで、クラスを
aria-current="page"に置き換えます。このリンクのアドレスは表示中のページなので、スクリーンリーダーは「マグ、現在のページ、リンク」のように現在のページとして読みます。 - 塗りつぶしの見た目を
[aria-current="page"]から描きます。選ばれて見えるリンクと、読み上げで選ばれているリンクが、必ず同じになります。 - 絞り込みの行の下に、視覚的に隠した空の
role="status"領域を置きます。最初からページにあり、描き替えられる一覧の外にあるため、ここへの書き込みは、ブラウザーが変化として伝えます。 - 新しい一覧がそろったら、押されたリンクへ
aria-currentを移し、領域に「表示中:マグ」と書き込みます。スクリーンリーダーは、読み上げ中の内容を読み終えてからこのメッセージを読み、フォーカスはリンクに残るので、続けて別の絞り込みを試せます。 - 押されたリンクがすでに現在のものなら何もしません。効いている絞り込みの一覧を、もう一度取得することはありません。
これで修正前の例は直り、4.1.2を満たします。選んだ絞り込みがコードで示され、変化は起きたときに伝えられます。4.1.2が求めるのはこの目印ですが、フォーカスのあるリンクで aria-current が変わったことをスクリーンリーダーが読むかどうかは、ここでは確認していないため、メッセージで言葉にして伝えます。
この方法を選ぶ理由:クラスではなく状態から見た目を決める
どちらも、選んだ絞り込みを示し、何が変わったかを伝えます。その場での更新は、フォーカスを絞り込みの行に残したまま今の位置を保つので、「マグ」のすぐあとに「皿」を試せます。その代わり、ステータス領域と、目印・メッセージ・一覧をそろえ続ける処理が必要です。ページの読み込みは、更新のためのスクリプトも、そろえ続けるものも要りません。ブラウザーとスクリーンリーダーが、ほかのリンクと同じように扱うからです。その代わり、押すたびにページを読み込み、フォーカスとスクロールは先頭に戻ります。絞り込みがあまり押されない場合や、更新のスクリプトが速さのためだけにある場合は、ページを読み込ませます。いくつもの絞り込みを続けて試すページなら、その場での更新を残します。
リンクかボタンか。 自分のアドレスを持ち、新しいタブで開いたり、ブックマークや共有ができたりする絞り込みはリンクであり、リンクのままにします。アドレスを持たずに一覧だけを変える絞り込みはボタンです。押された状態が伝わらないトグルボタンのように aria-pressed を付けます。二つの役割の違いは、リンクと読み上げられ、Spaceキーで押せないボタンを参照してください。
aria-currentの値。 page を使います。リンクのアドレスは表示中のページで、絞り込みの行はページの集まりだからです。aria-current="true" もまとまりの中の現在の項目を示し、スクリーンリーダーは「現在」のように読みます。タブや選択肢、グリッドの行とセルのための aria-selected や、行を独自のキー操作を持つタブリストに変えてしまう role="tab" は使いません。
伝えるのは表示内容で、一覧全体ではない。 メッセージは、効いている絞り込みの名前を伝えます。残った商品の数も伝えるなら、押すたびに一度、同じメッセージに件数を入れます。件数が読み上げられない検索・絞り込み結果を参照してください。商品の一覧に aria-live を付けてはいけません。
領域は描き替える部分の外に置く。 ステータス領域は、ページのレイアウトか、絞り込みのコンポーネントのうちマウントされたままの部分に描きます。一覧の中や、一覧と一緒に置き換えられるブロックの中には置きません。メッセージと一緒に作られた領域は、読まれないことが多いからです。
並べ替えのリンク。 「並べ替え:新着順・価格の安い順・価格の高い順」のような行も同じです。今の並び順のリンクに aria-current="page" を付け、その場で更新するなら「価格の安い順に並べ替えました」のように伝えます。表の列見出しで並べ替える場合は、見出しに aria-sort を付ける別のパターンで、並べ替えできる表のトピックで扱います。
移動を止めるリンクが守るべきこと。 すべてのクリックで preventDefault() を呼ぶ処理は、CtrlキーやCmdキーを押しながらのクリックも止めてしまい、絞り込みを新しいタブで開けなくなります。修飾キー付きのクリックはブラウザーに任せます。また、popstate でも一覧を描き替え、「戻る」で前の絞り込みに戻ったとき、目印もそれに合わせて移します。どちらも4.1.2の不適合ではありませんが、リンクがリンクらしく動かなくなったときに失われるものです。
コントラスト テーマ。 Windowsのコントラスト テーマでは、黒い塗りつぶしがページの背景色に置き換わり、選んだリンクがほかと同じに見えます。太い枠線など、テーマでも残る目印を加えるか、@media (forced-colors: active) の中で Highlight と HighlightText で塗ります。ハイコントラストモードで消えるフォーカス・アイコン・選択状態を参照してください。
デザインの案
選んだ絞り込みは、どんな見た目でも読み上げで伝えられる
絞り込みの行の描き方を、ガイドと同じ色でさらに4通り示します。絞り込みをクリックすると選択が移ります。Tabキーで行をたどってみてください。3つはスクリーンリーダーが読み取れる場所で選択を示し、1つは動きでしか変化を見せません。
デザインファイルで
- 選んだ絞り込みを独立した状態として描く。塗りに加えて、チェックマーク、バー、太字のいずれかで示す。Windowsのコントラスト テーマでは塗りが消えるため。
- すべての絞り込みにホバーとフォーカスを描く。選んだものも含めて、どれもリンクのままだから。
- 押すたびにページが伝える言葉を、行の横に書いておく。読み上げだけで画面に出さない場合も書く。
合格
- チェックマーク付きのチップ 選んだチップには、#1d1d1fのチェックマークと太字が付きます。淡い#e6eef8の塗りに対して14.39:1です。塗りはページに対して1.17:1しかなく飾りにすぎません。選択を示すのはチェックマークと太さで、どちらもコントラスト テーマで残ります。
- タブのような下線の行 絞り込みを細い線の上に並べ、選んだものは太字にして、下に#1d1d1fの3ピクセルのバーを引きます(白に対して16.83:1)。ほかは#5f6368(6.05:1)ですが、選んだものの色との差は2.78:1しかないため、バーと太さで見分けます。見た目はタブでも、矢印キーを覚える必要のないリンクの行のままです。
- ピルの下の「表示中」の行 ガイドと同じピルの下に、#5f6368(6.05:1)の行を置き、押すたびに「表示中:マグ」に変わります。スマートフォンで一覧までスクロールしなくても変化が見え、スクリーンリーダーが読むのもこの行です。
基本原則:メッセージは対象のそばに出す
不合格
- 並び替わるグリッドWCAG 4.1.2 タイルが0.4秒で新しい位置へ滑り込みます。変化を見せて止まる動きです。ただ、変化を伝えるのはこの動きだけです。塗りつぶしはクラスで描かれ、何も読み上げられないため、スクリーンリーダーには「マグ、リンク」と聞こえるだけで、変化はまったく伝わりません。
修正の確認
5項目、マウス不要
確認方法: スクリーンリーダー、キーボード、強制配色
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。絞り込みのコンポーネント、一覧のテンプレート、ページのレイアウトを変更した際は、再度確認します。
スクリーンリーダーでの role="status"、aria-current="page"の読まれ方
制限
ライブリージョンの読み上げはスクリーンリーダーやブラウザーによって異なり、続けて押すと、politeのメッセージが読まれないこともあります。このガイドは、一つずつ条件を選ぶリンクが1行に並ぶ場合を扱います。いくつも同時にチェックして組み合わせる絞り込みは、多くの場合チェックボックスで作られ、その結果の伝え方は件数が読み上げられない検索・絞り込み結果で扱います。シングルページアプリケーションの画面全体を入れ替えるリンクは読み上げられないSPAの画面遷移で、サイトのメニューの現在のページは現在のページを見た目だけで示すナビゲーションで扱います。実際の絞り込みを、並べ替えやページ送りも含めて、利用者が使うスクリーンリーダーで確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
EaseWebのサービス
修正した問題を、次のリリースで再発させない
このガイドのような修正方法を、コーディングエージェントが従うルールと、CIのチェックに組み込みます。あわせて定期的に、キーボードとスクリーンリーダーで手動の再テストを行います。