トピックを検索
見た目と食い違う読み上げ順序
注文内容の欄は各金額を品名より前に書いて右へフロートさせ、配送方法の枠は列ごとに書かれています。そのため、スクリーンリーダーでは言葉の組み合わせが崩れます。
<li><span class="amount">$28</span> キャンバストート</li> 問題
スクリーンリーダーや読み上げ機能の利用者には、金額が品名より先に、配送方法がばらばらの列として聞こえ、価格を別の項目と結び付けてしまいます。
かばんのお店の注文画面に、注文内容の欄があります。各行は左に名前、右に金額で、「キャンバストート $28」「リネントート $35」「送料 $4」、最後に太字で「合計 $67」と並んでいます。スクリーンリーダーの利用者がこの欄を上から読むと、「$28。キャンバストート。$35。リネントート。$4。送料。$67。合計」と聞こえます。どの金額も名前より先に来ます。名前の後に金額が来ると思って聞く人は、各名前を次の金額と結び付けます。キャンバストートは$35、送料は$67に思え、合計には金額がありません。
注文内容の上には、二つの配送方法を示す小さな枠があります。画面では、「通常配送、$4、3〜5日」と「お急ぎ便、$9、翌日」の2行に見えます。スクリーンリーダーは「通常配送。お急ぎ便。$4。$9。3〜5日。翌日」と読みます。どの価格がどちらの配送方法のものかは、記憶に頼るしかありません。
WCAG 1.3.2は、内容の順序が意味に影響する場合に、正しい読み上げ順序をコードから判断できることを求めています。支援技術が読むのは、画面上の位置ではなくマークアップです。注文内容では、各金額を先に書き、float: right で行の右端へ寄せています。画面では名前、金額の順に見え、マークアップでは金額、名前の順です。配送方法の枠は、名前、価格、日数の3列として書かれ、flexboxで横に並べられています。画面では目が行に沿って横に読みますが、マークアップには横に読む行がありません。どちらの例でも、内容の意味を作る組み合わせ(名前とその金額)が、レイアウトの中にしか存在しません。
リーダー表示、ブラウザー自身の読み上げ、スタイルを外してコピーや印刷したページも、マークアップの順序に従います。そのため、影響はスクリーンリーダーの利用者だけにとどまりません。
10グループ中3グループに影響
- 全盲 (影響あり)
- 弱視 (影響あり)
- 色覚 (影響なし)
- ろう (影響なし)
- 難聴 (影響なし)
- 発話 (影響なし)
- 手の操作 (影響なし)
- 届く範囲・力 (影響なし)
- 認知 (影響あり)
- 光過敏 (影響なし)
- 視覚を使わない スクリーンリーダーはマークアップを上から順に読むため、金額が品名より先に届き、前の行から続いているように聞こえます。点字ディスプレイにも同じ順序で表示されます。
- 言語・認知・学習の能力が限られる 読み上げ機能で文章を追う人にも同じ崩れた順序で聞こえ、ハイライトが行の右端の金額から、行頭の品名へ戻ります。
- 視覚が限られる 画面拡大鏡の読み上げを使う人には誤った組み合わせが聞こえ、リーダー表示や独自のスタイルで読む人には、マークアップの順に金額が品名の前に見えます。
どの要素も正しく書かれています。リストには項目があり、金額はspanで、枠はdivの集まりです。テキストが描かれる位置とマークアップ上の位置を比べるaxeのルールはないため、自動チェックは何も報告しません。違いが問題になるかどうかは、意味の問題です。本文の横のサイドバーは本文の前でも後でも構いませんが、金額が対象の項目より先に来るのは困ります。注文内容を新しい書き方に直すよう頼まれたAIは、フロートを flex-direction: row-reverse に置き換えることが多く、見た目と一緒に誤った順序も残ります。EaseWebの診断では、テキストより前に書かれて右へフロートした短い値、描画の順序とマークアップの順序が違うブロック、横に並べた列で作られた行を、人が確認する項目として挙げます。
試してみる
スクリーンリーダーと同じ順に注文内容を読み、どの金額がどの名前の後に来るか見てください。
パネルには、スクリーンリーダーが上から読んだ内容が出ます。「読み上げ順を表示」をオンにすると、各部分にその順の番号が付きます。どの金額も自分の名前の後に来ていますか?「問題2」は、列ごとに書いた配送方法の枠です。
問題あり 修正できますか?
- $28 キャンバストート
- $35 リネントート
- $4 送料
- $67 合計
上から読むと、スクリーンリーダーの読み上げ:
- 注文内容
- $28
- キャンバストート
- $35
- リネントート
- $4
- 送料
- $67
- 合計
修正方法
読む順にソースを書くか、位置のずれた値を、所属する対象とテキストで結び付けます。
- 1順序が意味を持つ箇所では、マークアップがその順序を伝える。その順に書くか、各項目が所属先を名指しする。
- 2行と列で描くデータは、表として行ごとに書くか、各値が自分の行を名指しする。
- 3幅によってレイアウトが並べ替わるため、すべてのブレークポイントで確認し、スタイルを外しても読む。
品名より前に書き、右へフロートさせた金額
<ul class="summary"> <li><span class="amount">$28</span> キャンバストート</li> <li><span class="amount">$35</span> リネントート</li> <li><span class="amount">$4</span> 送料</li> <li class="total"><span class="amount">$67</span> 合計</li></ul>読む順に書いたソース
html
<ul class="summary"> <li><span>キャンバストート</span> <span class="amount">$28</span></li> <li><span>リネントート</span> <span class="amount">$35</span></li> <li><span>送料</span> <span class="amount">$4</span></li> <li class="total"><span>合計</span> <span class="amount">$67</span></li></ul>html
<table class="delivery"> <tr> <th scope="row">通常配送</th> <td>$4</td> <td>3〜5日</td> </tr> <tr> <th scope="row">お急ぎ便</th> <td>$9</td> <td>翌日</td> </tr></table>この方法を選ぶ理由:ソースは読む順に書く
このように書かれるのは、フロートのためです。フロートは、それより前に書かれた内容より上には置けません。名前がどんな長さでも金額を行の1行目にそろえるため、金額を先に書く習慣があります。Bootstrap 3の公式ドキュメントもリストのバッジをこの形で書いており、当時のテーマにはいまも残っています。見た目は正しくても、スクリーンリーダーは各金額を名前より先に、前の行のすぐ後で読みます。行をflexboxと flex-direction: row-reverse で書き直しても、見た目と一緒に誤った順序がそのまま残ります。
マークアップで各名前が金額より先に来て、flexboxが金額を動かさずに行の右端へ寄せるため、注文内容は「キャンバストート $28」と読まれ、見た目は変わりません。説明リスト(dl で、名前を dt、金額を dd にする)や表でも構いません。配送方法は1行に一つの方法を書いた表になり、行ごとに読まれます。スクリーンリーダーの表の操作でも、価格がどの配送方法のものか分かります。
どちらも基準を満たします。おすすめは、読む順にソースを書く方法です。順序そのものを直すため、スクリーンリーダー、読み上げ機能、リーダー表示、スタイルを外したページのどれにも画面と同じ順序が届き、合わせて保守するものも増えません。注文内容のテンプレートでフロートをflexboxに置き換え、配送方法の枠を表に書き換える必要があります。隠したテキストはマークアップをそのまま使えるため、テーマや外部のウィジェットを変えられない場合に役立ちます。ただし、スクリーンリーダーの利用者には名前が繰り返され、マークアップに従うほかの人には崩れた順序が残ります。
float: right は、内容をマークアップ上の位置から離れた場所に描く方法の一つにすぎません。次の指定も同じ結果になるため、値が名前やラベルに属している箇所では検索してください。
- 横のテキストより前に書いた要素への
float: right(またはinline-end):このガイドの例です。 flex-direction: row-reverseとcolumn-reverse、order:行や列を反転させたり並べ替えたりします。フロートをflexboxに移すと、よくこの形になります。grid-template-areas、grid-row、grid-columnによるグリッドの配置:どの子要素もどこにでも置けます。- 絶対位置指定:バッジや価格を流れから外し、枠の角などへ移します。
レイアウトが並べ替わるのは、ある幅だけのこともよくあります。スマートフォンで行を column-reverse の縦並びにし、金額を名前の上に出す場合は、その幅だけが誤りになります。ブレークポイントごとに確認してください。
違いがすべて問題になるわけではありません。フロートした写真は段落の前でも後でも構いませんし、独立した二つのカードはどちらの順でも、サイドバーは本文の前でも後でも読めます。問題になるのは、意味が変わる違いです。項目より先の金額、前提となる手順より先の手順、値の後のラベルがそうです。新しいCSSの reading-flow プロパティを使うと、一部のブラウザーはflexやgridのコンテナーを描画の順に読み、Tabで移動します。ただし、フロートには効かず、すべてのブラウザーが対応しているわけでもないため、ソースを直してください。
列を並べる古い方法でも、同じ問題が起きます。直線化するとセルの順序が崩れるレイアウト用の表も、スペース、タブ、改行でそろえた列のテキストも、同じように失敗し、ひと続きの崩れた文として読まれます。本当の行と列は表にし、それ以外の配置はCSSに任せてください。
並べ替えた項目がリンクやボタンのようにフォーカスを受け取る場合、同じ食い違いがTabキーの移動もレイアウトと逆向きにします。その面はページ内を飛び回るフォーカス順序で扱っています。
AI コーディングアシスタントで修正しますか? このガイドを Markdown で取得
修正の確認
マウスを使わない4つの確認
確認方法: スクリーンリーダー、スタイルを無効化
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。レイアウトやコンポーネントのスタイルを変更した際は、再度確認します。
制限
このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。対象は、短い注文内容の欄と、選択肢の小さな枠です。ドラッグで並べ替えるリスト、データグリッド、カルーセルは、それぞれの設計パターンに従い、別の確認が必要です。順序が意味を変えるかどうかは内容に対する判断のため、実際のページをスクリーンリーダーで、またスタイルを外して読んでください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
参考資料
コードを更新しても、使いやすさを保つために
ガイドの内容を、コーディングエージェントやCIで使える開発ルールにまとめます。更新後は、キーボードとスクリーンリーダーで再テストし、問題が再発していないか確認します。