セマンティック HTML 要素の DOM 位置によって提供されるデフォルトのタブ順序は便利ですが、タブ順序を変更する必要がある場合があります。HTML 内の要素を移動するのが理想的ですが、現実的でない場合があります。このような場合は、tabindex
HTML 属性を使用して、要素のタブ位置を明示的に設定できます。
tabindex
は任意の要素に適用できますが、すべての要素で有用であるとは限りません。また、整数値の範囲を指定します。tabindex
を使用すると、フォーカス可能なページ要素の明示的な順序を指定したり、フォーカスできない要素をタブ順序に挿入したり、タブ順序から要素を削除したりできます。次に例を示します。
tabindex="0"
: 要素を自然なタブ順に挿入します。要素にフォーカスを設定するには、Tab キーを押します。また、focus()
メソッドを呼び出して要素にフォーカスを設定することもできます。
tabindex="-1"
: 要素を自然なタブ順序から削除します。ただし、要素の focus()
メソッドを呼び出すと、要素にフォーカスを設定できます。
tabindex="5"
: tabindex が 0
より大きい場合、その要素は自然なタブ順の先頭に移動します。tabindex が 0
より大きい要素が複数ある場合、タブ順序はゼロより大きい最小値から始まり、順に上昇します。
これは、ヘッダー、画像、記事のタイトルなど、入力以外の要素に特に当てはまります。可能であれば、DOM シーケンスで論理的なタブ順序が提供されるようにソースコードを配置することをおすすめします。tabindex
を使用する場合は、ボタン、タブ、プルダウン、テキスト フィールドなどのカスタム インタラクティブ コントロールに限定します。つまり、ユーザーが入力を期待する要素に限定します。
tabindex
は、インタラクティブなコンテンツにのみ追加してください。重要なコンテンツ(キー画像など)であっても、スクリーン リーダーのユーザーはフォーカスを追加しなくてもコンテンツを理解できます。
ページレベルでフォーカスを管理する
シームレスなユーザー エクスペリエンスを実現するために tabindex
が必要な場合があります。たとえば、さまざまなコンテンツ セクションを持つ堅牢な単一ページを作成する場合、すべてのコンテンツが同時に表示されることはありません。ページを更新せずに、ナビゲーション リンクによって表示されるコンテンツが変更される可能性があります。
この場合、選択したコンテンツ領域を特定し、-1
の tabindex
を指定して、その focus
メソッドを呼び出します。これにより、コンテンツが自然なタブ順序で表示されなくなります。この手法はフォーカスの管理と呼ばれ、ユーザーが認識するコンテキストをサイトのビジュアル コンテンツと同期させます。
コンポーネントのフォーカスを管理する
カスタム コンポーネントなど、コントロール レベルでフォーカスを管理する必要がある場合もあります。
たとえば、select
要素は基本的なフォーカスを受け取ることができますが、フォーカスを受け取った後、矢印キーを使用して選択可能なオプションをさらに表示できます。カスタム select
要素を作成する場合は、キーボード ユーザーがコントロールを操作できるように、その動作を再現することが重要です。
実装するキーボードの動作を把握するのは難しい場合があります。Accessible Rich Internet Applications(ARIA)の作成方法ガイドでは、コンポーネントの種類と、サポートされているキーボード アクションの種類について説明しています。
ラジオボタンのセットのように見えるが、外観と動作に独自の工夫を凝らしたカスタム要素を作成している場合などです。
<radio-group>
<radio-button>Water</radio-button>
<radio-button>Coffee</radio-button>
<radio-button>Tea</radio-button>
<radio-button>Cola</radio-button>
<radio-button>Ginger Ale</radio-button>
</radio-group>
必要なキーボード サポートを確認するには、ARIA 作成方法ガイドをご覧ください。セクション 2 には、ラジオ グループの特性表など、新しい要素に最も近い既存のコンポーネントを含む、デザイン パターンのリストが含まれています。
サポートする必要がある一般的なキーボード動作の一つに、上下左右の矢印キーがあります。この動作を新しいコンポーネントに追加するには、移動タブインデックスという手法を使用します。
移動タブインデックスは、現在アクティブな子要素を除くすべての子要素の tabindex
を -1 に設定することで機能します。
<radio-group>
<radio-button tabindex="0">Water</radio-button>
<radio-button tabindex="-1">Coffee</radio-button>
<radio-button tabindex="-1">Tea</radio-button>
<radio-button tabindex="-1">Cola</radio-button>
<radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>
コンポーネントはキーボード イベント リスナーを使用して、ユーザーが押したキーを判断します。この場合、以前にフォーカスされていた子の tabindex
を -1 に設定し、フォーカスされる子の tabindex
を 0 に設定して、その子のフォーカス メソッドを呼び出します。
<radio-group>
<!-- Assuming the user pressed the down arrow, we'll focus the next available child -->
<radio-button tabindex="-1">Water</radio-button>
<radio-button tabindex="0">Coffee</radio-button> // call .focus() on this element
<radio-button tabindex="-1">Tea</radio-button>
<radio-button tabindex="-1">Cola</radio-button>
<radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>
ユーザーが最後の子(フォーカスを移動する方向に応じて最初の子)に到達すると、フォーカスは最初の子(または最後の子)に戻ります。
次の例をお試しください。DevTools で要素を調べて、タブインデックスがラジオボタンから次のラジオボタンに移動する様子を確認します。
モーダルとキーボード トラップ
フォーカスを手動で管理すると複雑な状況になる可能性があるため、手動での管理は避けてください。たとえば、フォーカスを管理し、タブの動作をキャプチャしようとする自動入力ウィジェットでは、完了するまでユーザーが離れないようにします。これはキーボード トラップと呼ばれ、ユーザーに大きなストレスを与える可能性があります。
WCAG のセクション 2.1.2 では、キーボードのフォーカスが特定のページ要素でロックまたはトラップされないようにすることが規定されています。ユーザーはキーボードのみを使用して、すべてのページ要素を移動できる必要があります。
このルールの例外はモーダルです。ただし、モーダルを作成する際は、tabindex
を使用しないでください。inert
を使用すると、ユーザーが要素を誤って操作できないようにすることができます(意図的なキーボード トラップ)。デフォルトで無効になっている <dialog>
要素を使用して、ユーザー向けのモーダルを作成し、モーダルの外側のクリックとタブをブロックします。これにより、ユーザーは必要な選択に集中できます。