Tabindex の使用

セマンティック HTML 要素の DOM 位置で決まる既定のタブオーダーは便利ですが、タブオーダーの変更が必要になる場合もあります。HTML 内の要素を移動するのが理想的ですが、現実的でない場合があります。このような場合は、tabindex HTML 属性を使用して、要素のタブ位置を明示的に設定できます。

対応ブラウザ

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.5。
  • Safari: 3.1。

ソース

tabindex は任意の要素に適用できますが、必ずしもすべての要素で有用であるとは限りません。また、広範な整数値を使用します。tabindex を使用すると、フォーカス可能なページ要素の明示的な順序を指定したり、フォーカス不可能な要素をタブオーダーに追加したり、要素をタブオーダーから削除したりできます。次に例を示します。

tabindex="0": 要素を通常のタブオーダーに追加します。要素は Tab キーを押すとフォーカスされ、focus() メソッドを呼び出すことでフォーカスがあたります。

tabindex="-1": 通常のタブオーダーから要素を削除しても、focus() メソッドを呼び出すことでまだ要素にフォーカスできます。

tabindex="5": 0 より大きい tabindex を指定すると、その要素が通常のタブオーダーの前に移動します。複数の要素の tabindex が 0 より大きい場合、タブオーダーは 0 より大きい最小値からスタートし、次第に大きい値の要素に移動します。

これは、特にヘッダー、画像、記事のタイトルなどの非入力要素に当てはまります。可能な場合は、DOM 順序でタブオーダーが論理的になるようにソースコードを配置することをおすすめします。tabindex を使用する対象は、ボタン、タブ、プルダウン、テキスト フィールドなどのカスタム インタラクティブ コントロール、つまり、ユーザーが入力を想定する要素に制限してください。

tabindex は、インタラクティブなコンテンツにのみ追加してください。重要なコンテンツ(キー画像など)であっても、スクリーン リーダーのユーザーはフォーカスを追加しなくてもコンテンツを理解できます。

ページレベルでのフォーカスの管理

シームレスなユーザー エクスペリエンスを実現するために tabindex が必要な場合があります。たとえば、さまざまなコンテンツのセクションを含む堅牢なシングルページを構築し、すべてのコンテンツを一度に見ることはできません。つまり、ナビゲーション リンクをクリックすると、ページを更新せずに表示可能なコンテンツが変更される可能性があります。

この場合、選択したコンテンツ領域を特定し、tabindex-1 を指定して、その focus メソッドを呼び出します。これにより、コンテンツが通常のタブオーダーで表示されなくなります。この手法はフォーカスの管理と呼ばれ、ユーザーが知覚する状況を、サイトの視覚的なコンテンツに同期させることができます。

コンポーネントのフォーカスを管理する

カスタム コンポーネントなど、コントロール レベルでフォーカスを管理する必要がある場合もあります。

たとえば、select 要素は基本的なフォーカスを受け取ることができますが、フォーカスがあたると、カーソルキーを使用して追加の選択可能なオプションを表示できます。カスタムの select 要素を作成する場合は、キーボード ユーザーがコントロールを操作できるように、その動作を再現することが重要です。

実装するキーボードの動作を把握するのが難しい場合があります。Accessible Rich Internet Applications (ARIA) Authoring Practices ガイドには、タイプ別コンポーネントの一覧と、サポートしているキーボードの操作が記載されています。

一連のラジオボタンに類似した、独自の外観と動作を持つカスタム要素を作成しているとします。

<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 には、新しい要素に最も近い既存のコンポーネントであるラジオグループの特性の表など、デザイン パターンのリストが含まれています。

サポートする必要がある一般的なキーボード動作の 1 つは、上下左右の矢印キーです。この動作を新しいコンポーネントに追加するには、tabindex の移動というテクニックを使用します。

tabindex の移動を機能させるには、現在アクティブな子を除いて、すべての子の 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 にして、その子の focus メソッドを呼び出します。

<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 で要素を調べると、tabindex が次のラジオボタンに移動する様子がわかります。

モーダルとキーボードのトラップ

フォーカスを手動で管理すると複雑な状況になる可能性があるため、手動で管理しないことをおすすめします。たとえば、フォーカスを管理し、タブの動作をキャプチャしようとするオートコンプリート ウィジェットでは、完了するまでユーザーがウィジェットを離れないようにします。これはキーボード トラップと呼ばれ、ユーザーに大きなストレスを与える可能性があります。

WCAG のセクション 2.1.2 では、キーボードのフォーカスが特定のページ要素でロックまたはトラップされないようにすることが規定されています。ユーザーはキーボードのみを使用して、すべてのページ要素間を移動できる必要があります。

このルールの例外はモーダルです。ただし、モーダルを作成する際は、tabindex を使用しないでください。inert を使用すると、ユーザーが要素を誤って操作できないようにすることができます(意図的なキーボード トラップ)。デフォルトで無効になっている <dialog> 要素を使用して、ユーザー向けのモーダルを作成し、モーダルの外側のクリックとタブをブロックします。これにより、ユーザーは必要な選択に集中できます。