ページ内を飛び回るフォーカス順序
CSSで並べたボタンの左右を画面上だけ逆にしているため、マークアップの順序と食い違い、Tabキーが見た目と逆向きに動きます。
問題
キーボード利用者は、フォーカスがレイアウトと逆向きに動くのを見て現在位置を見失い、違うボタンを押すことがあります。
文房具店の注文画面は、右寄せのバーに三つの操作が並んでいます。画面では左から「注文を確定」「あとで保存」「かごに戻る」の順に見えます。キーボード利用者がバーにTabで入ると、最初のフォーカスは右端の「かごに戻る」に当たります。次のTabで中央の「あとで保存」、その次で左端の「注文を確定」へ移ります。フォーカスの枠は、ページを読む向きとは逆に動き、次にどのボタンへ移るのか分かりません。
デザインでは主な操作を先頭に置きたかったため、CSSで行に flex-direction: row-reverse を指定しています。マークアップは、戻る、保存、確定の順のままです。ブラウザーは画面上の位置ではなくマークアップの順にフォーカスを移すため、見た目の順序とフォーカスの順序が逆になります。WCAG 2.4.3は、意味と操作性が保たれるフォーカス順序を求めています。この例では、行は一方向に読めるのに、フォーカスは反対向きに進みます。
キーボード利用者やスイッチ利用者は、フォーカスだけが現在位置を知る手がかりです。画面拡大鏡を使う人はページの一部しか見えないため、右端から左端へ飛ぶ枠を見失いやすくなります。スクリーンリーダー利用者には、マークアップの順に読み上げられるため、目で見ている同僚の説明と食い違います。最初に見えるボタンにフォーカスがあると思ってEnterを押すと、「かごに戻る」が実行され、注文画面から離れてしまいます。
バーの中の操作は、どれもフォーカスでき、名前もあり、到達できるため、自動チェックが指摘するものがありません。DOMだけを見れば、正しいリストです。問題に気づくには、各要素が描画される位置とTab順の位置を比べる必要があり、その検査をするツールは多くありません。生成されたコードは、デザイン案に合わせて order や row-reverse を足し、マークアップを直さないことで、問題を悪化させます。
試してみる
Tabキーを押して、フォーカスがどちらへ動くか見てください。
Tabキーで三つのボタンを順に移動してください。フォーカスは、行を読む向き(左から右)に動きますか?
直前のフォーカス移動: (まだなし)
再現デモです。「問題あり」は意図的にアクセシブルでない状態にしています。
修正方法
マークアップをデザインの順に並べ替えるか、逆転させるCSSを外します。
- 1マークアップの順序がフォーカス順序になる。CSSでフォーカスできる要素を逆転・並べ替えしない。
- 2tabindexは0か-1だけを使い、正の数は使わない。
- 3狭い幅ではレイアウトが並べ替わるため、ブレークポイントごとに確認する。
html
<div class="actions"> <a href="/basket">かごに戻る</a> <button type="button">あとで保存</button> <button type="submit">注文を確定</button></div>css
.actions { display: flex; flex-direction: row-reverse; gap: 12px;}画面では左から、確定、保存、戻るの順に見えます。フォーカスは戻る、保存、確定の順に移ります。CSSは見た目だけを変え、キーボードとスクリーンリーダーが使う順序をそのままにしています。
マークアップをデザインどおりの順に並べ、CSSの逆転をなくしました。Tabキーは「注文を確定」「あとで保存」「かごに戻る」の順に、ページを読む向きどおり左から右へ進みます。見た目は変わりません。
どちらも、画面上の順序とフォーカスの順序が一致するため、基準を満たします。マークアップを並べ替える方法は、承認済みのデザインを変えずに済みますが、テンプレートと、それに頼るテストやスナップショットの修正が必要です。逆転を外す方法は、コードの変更はほぼ要りませんが、バーの見た目が変わるため、デザイナーの合意が必要です。内容にとって正しい順序で選んでください。マークアップの順が自然な流れで、逆転がスタイルだけの理由なら逆転を外し、デザインが固定されているならマークアップを直します。
row-reverse は原因の一つにすぎません。order プロパティ、column-reverse、grid-area や grid-row によるグリッドの配置、float、絶対位置指定は、いずれもマークアップの位置を変えずに画面上の位置だけを動かせます。フォーカスできる要素の周りでは、これらを検索してください。
順序を tabindex="1" や "2" で直してはいけません。正の値を持つ要素は、ページのほかの要素よりも先に移動の対象になります。数字がボタンをページの流れから切り離し、後から追加する要素にも番号が必要になります。フォーカスできるようにしたい独自の操作には tabindex="0" を、スクリプトでフォーカスを移すだけの要素には -1 を使います。
ブレークポイントでレイアウトが変わると、二つ目の問題がよく起きます。スマートフォンでサイドバーが本文の下に移る、カードの画像が見出しの上に移るといった場合は、その幅でも同じ確認が必要です。右から左へ書く言語は、row-reverse ではなく dir="rtl" で扱ってください。レイアウトとフォーカス順序が一緒に反転します。
順序は、ピクセル単位で一致させるのではなく、意味を保つ必要があります。わずかにずれた装飾的な操作は問題になりませんが、依存する手順より先に来る手順は問題です。メニューやエラーメッセージなど必要なときに現れる内容は、開く操作要素の隣に挿入するか、開いたときにフォーカスを受け取るようにします。ダイアログについては、モーダルのガイドを参照してください。新しいCSSの reading-flow を使うと、対応するブラウザーでは両方をそろえられますが、すべてのブラウザーが対応しているわけではないため、マークアップを直してください。
修正の確認
マウスを使わない4つの確認
確認方法: キーボード、スクリーンリーダー、ズーム
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。レイアウトやコンポーネントのスタイルを変更した際は、再度確認します。
制限
このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。対象は、固定された操作の行です。データグリッド、カルーセル、矢印キーでフォーカスを動かすウィジェットは、それぞれの設計パターンに従い、別の確認が必要です。順序が意味を保っているかどうかは内容に対する判断のため、実際のページで操作全体を確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
コードを更新しても、使いやすさを保つために
ガイドの内容を、コーディングエージェントやCIで使える開発ルールにまとめます。更新後は、キーボードとスクリーンリーダーで再テストし、問題が再発していないか確認します。