トピックを検索
スクリーンリーダーで読めないプログレスバーとメーター
アップロードのバーをdivで描いたり、名前がなく値も動かないprogressbarロールを付けたりしているため、どこまで進んだか、いつ終わったかがスクリーンリーダーに伝わりません。
<div class="bar"><div class="fill" style="width: 60%"></div></div> 問題
スクリーンリーダーの利用者は、アップロードを始めても、どこまで進んだか、まだ続いているか、終わったかが分かりません。
問い合わせフォームでファイルを添付できます。report.pdfを選んで「アップロード」を押すと、ファイル名の下の灰色のバーが数秒かけて青く伸び、いっぱいになるとチェックと「アップロード完了」が表示されます。画面が見える人は、バーが伸びるのを見て待ちます。スクリーンリーダーの利用者には、ボタンを押しても何も聞こえません。探しに行っても、バーがまったく見つからないか、半分以上伸びているのに「プログレスバー、0%」と読まれます。始まったのか、あとどれくらいか、終わったのかが分からず、もう一度押したり、添付される前にフォームを送ったりしてしまいます。
足りないものは2つあります。1つ目はバーそのものです。ひとつの形では、バーは2つの div 要素、つまり土台と、スクリプトが width を変える塗りでできています。ロールも名前も値もないため、支援技術からは何もないのと同じです。もうひとつの形では role="progressbar" が付いていますが、名前がなく、スクリプトは塗りを動かすだけで aria-valuenow を変えません。そのため、スクリーンリーダーは最後まで0%と読みます。達成基準4.1.2は、スクリプトで作られる部品の名前とロールを支援技術が判別でき、値の変化が支援技術に伝わることを求めています。値を表示するだけのバーが「ユーザーインターフェースコンポーネント」に当たるかは議論があり、axeは名前のないプログレスバーを1.1.1 非テキストコンテンツとして報告します。どちらの見方でも、バーの意味が支援技術に届く必要があり、修正方法は同じです。
2つ目は知らせです。「半分完了」や「アップロード完了」はステータスメッセージです。フォーカスを移さずに、処理の進み具合と結果を伝えるもので、4.1.3の対象です。その解説書でも、ときどき読み上げられるプログレスバーが例に挙がっています。プログレスバーはライブリージョンではないため、正しく作ったバーでも、値が変わったときに読み上げられるとは限りません。スクリーンリーダーが自分で追うかどうか次第です。たとえばNVDAは、初期設定でプログレスバーが変わるたびにビープ音を鳴らし、進むほど音が高くなります。一方、利用者がバーに移動するまで何も言わないスクリーンリーダーもあります。ビープ音では、アップロードが終わったことも、失敗したことも分かりません。
バーは見ている人に向けて描かれるため、見ていない人には、どこまで進んだかも、終わった瞬間も伝わりません。アップロード中に次の入力欄へ進んだ、画面が見える人も同じです。
10グループ中2グループに影響
axeは名前のない role="progressbar" や role="meter" を報告しますが、div 要素で描いたバーにはチェックするロールがありません。また、HTML標準の progress 要素や meter 要素の名前は確認しません。ある瞬間のページしか見ないため、塗りが伸びても aria-valuenow が0のままであることや、終了が伝えられないことは、どのスキャンにも分かりません。バーを直すよう頼むと、コーディングアシスタントは role="progressbar" と3つの aria-value* 属性を固定の数字で付けることがあります。これでは無音が誤った値に変わるだけです。バーと割合の表示を aria-live で囲み、1%ごとに読ませる例もあります。アップロードの最中にスクリーンリーダーで聞いて、初めて分かります。
試してみる
「アップロード」でEnterキーを押し、バーが伸びる間の読み上げを聞いてください。
下の欄に、アップロード中のスクリーンリーダーの読み上げと、バーに移動したときに読まれる内容が出ます。進み具合と終わったことが聞こえますか?
問題あり 修正できますか?
アップロード中:report.pdf
アップロード完了
スクリーンリーダーの読み上げ:
(「アップロード」を押してください)
修正方法
バーに名前と、描画と一緒に動く値を持たせ、区切りの進み具合と終了を伝えます。
- 1何を測るバーかを、名前かそばのテキストで伝える。
- 2値は、塗りを描くコードで一緒に設定する。
- 3区切りと終了をステータス領域で伝える。1%ごとには伝えない。
Divで描いたバー
<p>アップロード中:report.pdf</p><div class="bar"><div class="fill" style="width: 0%"></div></div><p class="done" hidden>アップロード完了</p>HTML標準のprogress要素
<label for="upload-bar">アップロード中:report.pdf</label><progress id="upload-bar" max="100" value="0">0%</progress><p class="done" hidden>アップロード完了</p><p id="upload-status" role="status" class="visually-hidden"></p>この方法を選ぶ理由:まずHTMLの要素を使う
バーにはロールも名前も値もないため、スクリーンリーダーにはファイル名のあとに何もありません。「アップロード完了」も、表示されるだけで読み上げられません。ここでの upload() はサイト独自のアップロード処理を表し、XMLHttpRequest の upload の進捗イベントのように、送信中に割合を知らせるものとします。
ブラウザーにとって progress はプログレスバーです。labelが名前になり、max に対する value が支援技術に伝わるため、スクリーンリーダーで移動すると、名前、ロール、値が読み上げられます。要素の中のテキストは、バーを描けないブラウザー向けの代わりの表示で、名前にはなりません。ステータス領域は最初から空のままページにあるため、メッセージは控えめに、4分の1ずつ読み上げられ、最後に「report.pdfをアップロードしました」と読まれます。代わりに見た目の自由は減ります。バーはブラウザーが描くため、色を変えるには ::-webkit-progress-value や ::-moz-progress-bar のような、ブラウザーごとの疑似要素が必要です。
3つとも、バーの進み具合を最新の言葉で伝え、同じステータス領域で区切りと終了を知らせます。HTML標準の progress 要素は、コードが最も少なく済みます。ロール、labelからの名前、値はブラウザーが用意し、スクリプトは value を設定するだけです。疑似要素で見た目を整えられるなら、これを選びます。独自のロールなら、デザインのとおりにバーを描けますが、塗りと一緒に属性を保つのはスクリプトの役目です。差し替えられないコンポーネントのバーや、土台と塗り以上の表現が必要なデザインに向いています。値をテキストで書く方法は、既存のバーへの変更が最も小さく、誰にでも数字が見えます。バーの周りの文言は変えられても、バーそのものは変えられないときに選びます。その場合、スクリーンリーダーにはプログレスバーとして伝わらず、NVDAが進み具合に応じて鳴らすビープ音もなくなることを受け入れることになります。
1%ごとではなく、区切りで伝えます。 アップロードは何十回も進捗イベントを出し、そのたびにステータスメッセージを出すと、利用者は数字の列を聞き続けることになります。数秒で終わる処理なら、4分の1ごとが合います。大きなエクスポートのような長い処理では、10秒ほどごとか、「準備中」「アップロード中」「処理中」のような段階ごとに伝えます。2〜3秒で終わるなら、終了だけを伝えます。バーや、バーと一緒に変わる割合の表示に aria-live を付けないでください。変化がすべて読み上げられます。テクニックARIA25のようにバーのそばにライブのテキストを置く方法は、スクリプトがそのテキストを区切りでだけ更新するなら使えます。
割合ではなく手順の場合。 チェックアウトや会員登録で「ステップ2/4」をバーで示す場合、値は割合ではありません。スクリーンリーダーは aria-valuenow を割合として読むことが多く、1〜4の範囲の2が「2パーセント」と読まれることがあります。role="progressbar" に aria-valuetext="ステップ2/4:お届け先" を設定するか、手順をリストで示し、今の手順に aria-current="step" を付けます。リストのほうがバーより多くを伝えられます。
量が分からない場合。 どこまで進んだか分からないなら、値を省きます。value 属性のない progress 要素や、aria-valuenow のない role="progressbar" は、何かが進行中であることだけを示す不確定の状態です。これは読み込み中の表示であり、読み上げられない読み込み中の表示で別のパターンを扱っています。
メーター。 メーターは、使用中のストレージやパスワードの強度のように、決まった範囲の中の測定値を示すもので、作業の進み具合を示すものではありません。HTMLの仕様も、プログレスバーに meter を使わないよう定めています。名前は progress と同じようにlabelで付けます。たとえば <label for="storage">使用中のストレージ</label> のあとに <meter id="storage" min="0" max="10" value="7.2"> を置きます。メーターの読み上げはスクリーンリーダーによってばらつきがあります。2022年に公開されたテストでは、NVDAはメーターをプログレスバーと読み、macOSのVoiceOverはスタイルを付けたメーターを飛ばし、どれも低い値や高い値の区切りを読みませんでした。そのため、値をメーターのそばにテキストでも書き(「7.2 GB / 10 GB」)、色の意味も言葉で示します(「強度:弱い」)。独自のメーターには role="meter"、名前、aria-valuenow、aria-valuemin と aria-valuemax(既定値は0と100)、単位を含む aria-valuetext を付けます。
色と強制配色。 値を示すのが塗りだけの場合、塗りは意味を持つ図形なので、土台に対して3:1のコントラストが必要です。コントラストが足りない入力欄・アイコン・フォーカス枠を参照してください。background-color で描いた塗りは、背景が置き換えられる強制配色のテーマでは消えてしまいます。@media (forced-colors: active) の中で background-color: CanvasText を指定します。
AI コーディングアシスタントで修正しますか? このガイドを Markdown で取得、または全ガイドをコーディングエージェントで使う。
デザインの案
バーは、控えめでも読み取れるように描けます。
進み具合の描き方を8通り示します。うち2つは動きます。スクリーンリーダーへの伝え方はガイドの修正で整っています。ここで見るのは、画面を見る人に進み具合が伝わるかです。
合格
アップロード中:report.pdf
トラックに対して3:1以上の塗り #e6e9eeのトラックに#1f5fa8の塗りで5.29:1です。値が塗りにしか表れないとき、塗りは意味を持つ図なので、1.4.11により3:1が必要です。アップロード中:report.pdf
控えめなバーと、横に書いた割合 薄い塗りはトラックに対して1.47:1しかありませんが、「60%」が値を文字で伝えるので、理解に塗りは必要なくなります。バーはデザインどおり控えめにできます。アップロード中:report.pdf
中央に数字のあるリング 同じ値を弧で示す形で、小さなカードやスマートフォンに向きます。値は数字が伝え、弧もトラックに対して5.29:1を保っています。お届け先ステップ2/4
区切りと、書き出したステップ 購入手続きや初期設定のように、進み具合が割合でなくステップの場合の形です。「ステップ2/4」が現在地を伝え、区切りはその要約です。アップロード中:report.pdf
新しい値へ滑らかに伸びる塗り 「再生」を押してください。値が変わるたびに塗りが0.4秒かけて伸び、値が止まれば止まります。動くのは進み具合を示すときだけです。「視差効果を減らす」設定では、滑らかに動かず切り替わります。
不合格
アップロード中:report.pdf
細く薄いバーだけWCAG 1.4.11 流行の4pxのバーです。#e6e9eeに#a8c4e6で1.47:1、文字もありません。値は塗りにしか表れず、多くの人には塗りの終わりが見分けられません。report.pdf
アップロード失敗で赤くなるWCAG 1.4.1 失敗したことを色だけで伝えています。赤が見分けにくい人には、進行中のバーと同じに見えます。横に「アップロードに失敗しました」と次にすることを書きます。report.pdfをアップロードしました
完了後も動き続ける縞模様WCAG 2.2.2 アップロードは終わっているのに、縞模様がフォームの横で止める手段のないまま流れ続けます。この見本は数秒で止まりますが、このパターン自体は止まりません。
修正の確認
マウスを使わない4つの確認
確認方法: スクリーンリーダー、キーボード
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。アップロードの処理や進捗表示のコンポーネントを変更した際は、再度確認します。
制限
プログレスバーの伝え方はスクリーンリーダーによって異なります。値を割合で読むもの、ビープ音を鳴らすもの、利用者が移動したときにだけ読むものがあり、メーターの対応はさらに不安定です。このガイドは、一つのページの一つの処理のバーを扱っています。量の分からないスピナーや待ち時間は読み上げられない読み込み中の表示で、「下書きを保存しました」のような進み具合以外のメッセージは画面に出ても読み上げられないステータスメッセージで扱っています。遅い場合や失敗する場合も含め、利用者が使うスクリーンリーダーで実際のアップロードを確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
参考資料
- WCAG Understanding: name-role-value(新しいタブで開きます)
- WCAG Understanding: status-messages(新しいタブで開きます)
- WCAG Technique ARIA25(新しいタブで開きます)
- developer.mozilla.org: progress(新しいタブで開きます)
- developer.mozilla.org: progressbar_role(新しいタブで開きます)
- developer.mozilla.org: meter_role(新しいタブで開きます)
- html.spec.whatwg.org: form-elements(新しいタブで開きます)
- htmhell.dev: 5(新しいタブで開きます)
コードを更新しても、使いやすさを保つために
ガイドの内容を、コーディングエージェントやCIで使える開発ルールにまとめます。更新後は、キーボードとスクリーンリーダーで再テストし、問題が再発していないか確認します。