実践Webアクセシビリティ

キーボードナビゲーションの操作順序を制御する:Tabindexの適切な使い方

Tags: アクセシビリティ, キーボード操作, Tabindex, HTML, 実装方法

はじめに:キーボードナビゲーションの重要性

Webアクセシビリティにおいて、キーボード操作だけでWebサイトやアプリケーションのすべての機能にアクセスできることは非常に重要です。マウスやポインティングデバイスの使用が困難な方(運動機能障がいのある方、一時的な怪我をしている方など)や、スクリーンリーダーを利用する方にとって、キーボードは主要な操作手段となります。また、キーボードショートカットに慣れているユーザーにとっても、効率的な操作のために不可欠です。

キーボードでの操作性確保には、インタラクティブな要素(リンク、ボタン、フォーム部品など)が適切にフォーカス可能であること、そしてフォーカスの移動順序が論理的であることが求められます。特に、フォーカスの移動順序は、ユーザーがコンテンツを認識し、迷わず操作を進める上で中心的な役割を果たします。

この記事では、HTMLのtabindex属性を用いて、Webページのフォーカス順序をどのように制御し、キーボードナビゲーションのアクセシビリティを高めるかについて、具体的な実装方法と注意点を解説します。

なぜ操作順序の制御が必要か

デフォルトの状態では、キーボードのTabキーやShift+Tabキーを押した際のフォーカス移動順序は、HTMLソースコード内の要素の出現順序に基づきます。多くの場合はこのデフォルトの順序で問題ありませんが、CSSによる視覚的な配置がソースコード順と大きく異なる場合や、JavaScriptによって動的にコンテンツが表示・非表示される場合など、視覚的な順序とソースコード順が一致しないことがあります。

このような不一致は、キーボードユーザーにとって混乱を招き、操作を困難にします。ユーザーは画面上で要素を見つけても、Tabキーを押しても期待した要素にフォーカスが移動せず、Webサイトの利用を断念してしまう可能性もあります。そのため、視覚的な並びや操作の論理的な流れに沿ったフォーカス順序を意図的に設計・実装することが不可欠です。

Tabindex属性とは?

tabindex属性は、要素がキーボードフォーカス可能であるかどうか、そしてもしフォーカス可能であれば、Tabキーが押された際のフォーカス移動順序を制御するために使用されるグローバル属性です。この属性は、ほとんどのHTML要素に指定できますが、その効果は要素の種類や指定する値によって異なります。

tabindex属性は、以下の3種類の値を持ちます。

  1. tabindex="-1":

    • 要素をデフォルトのタブ順から除外します。
    • ただし、JavaScriptのelement.focus()メソッドを使用すれば、プログラムからこの要素にフォーカスを移動させることが可能です。
    • 主に、非表示の要素や、特定のイベント発生時のみフォーカスを受け取るべき要素に使用されます(例: モーダルウィンドウがアクティブになった際の閉じるボタンやコンテナ要素)。
  2. tabindex="0":

    • 要素をデフォルトのタブ順に含めます
    • 要素自体のソースコード上の位置に基づいて、自然なタブ順序でフォーカス可能になります。
    • デフォルトでフォーカス可能ではない要素(例: <div>, <span>など)を、自然な順序のままキーボード操作の対象にしたい場合に主に使用されます。
  3. tabindex="1"以上の正の整数:

    • 要素をデフォルトのタブ順とは異なる、明示的に指定された順序に含めます。
    • tabindexの値が小さい要素から大きい要素へとフォーカスが移動します。同じ値を持つ要素間では、ソースコード上の出現順序に従います。
    • 非推奨です! この値を安易に使用すると、予想外のフォーカス順序を生み出し、管理が非常に困難になるため、特別な理由がない限り避けるべきです。後述の「避けるべきTabindexの使い方」で詳しく説明します。

デフォルトでフォーカス可能な要素(<a>, <button>, <input>, <select>, <textarea>など)は、tabindex属性を指定しない場合、自動的にソースコードの出現順にタブ順に含まれます。

Tabindexの具体的な使い方と注意点

1. デフォルト順序を変えずにフォーカス可能にする (tabindex="0")

デフォルトでフォーカス可能ではないが、キーボードユーザーに操作させたい、あるいはフォーカスを当ててコンテンツを認識させたい要素に使用します。最も一般的なユースケースは、ARIAロールやイベントリスナーを追加してインタラクティブな振る舞いを持たせた<div><span>などの要素です。

使用例: カスタムボタンのように振る舞うdiv要素をフォーカス可能にする場合。

<div role="button" tabindex="0" aria-label="設定を開く">
  設定アイコン
</div>

<span role="checkbox" tabindex="0" aria-checked="false">
  同意する
</span>

この場合、tabindex="0"を指定された要素は、その要素がHTMLソースコードに出現する位置に基づいて、通常のインタラクティブ要素と同じ順序でフォーカス可能になります。

2. デフォルト順序から除外する (tabindex="-1")

特定の条件下でのみフォーカスさせたい要素や、スクリプトで強制的にフォーカスを当てたい要素に使用します。

使用例: * ページロード時にフォーカスを避けたいが、特定の操作後にフォーカスさせたい要素。 * モーダルウィンドウがアクティブになった際に、そのモーダルコンテナ自体にフォーカスを当て、ページ全体のスクロールや不要な要素へのフォーカス移動を防ぎたい場合。

<div id="modalContainer" tabindex="-1" role="dialog" aria-labelledby="modalTitle">
  <!-- モーダルコンテンツ -->
  <h2 id="modalTitle">ダイアログタイトル</h2>
  <p>これはモーダルウィンドウの内容です。</p>
  <button>閉じる</button>
</div>

<script>
  // モーダルを開く処理の最後に実行
  document.getElementById('modalContainer').focus();
</script>

この例では、モーダルコンテナにtabindex="-1"を指定することで、通常のTabキー操作ではフォーカスされませんが、JavaScriptで明示的にフォーカスを当てることが可能になります。

3. 順序を明示的に指定する (tabindex="1"以上の値) - 非推奨とその理由

tabindex="1"以上の正の整数を使用すると、tabindexが指定されていない要素やtabindex="0"の要素よりも先にtabindexの値が小さい順にフォーカスが移動します。

例(非推奨のコード):

<!-- 非推奨な実装例 -->
<button tabindex="3">ボタン3</button>
<button tabindex="1">ボタン1</button>
<button tabindex="2">ボタン2</button>

この場合、Tabキーを押すと「ボタン1」→「ボタン2」→「ボタン3」の順にフォーカスが移動します。一見、意図した順序になるように見えます。

なぜ非推奨なのか?

結論として、特別な理由がない限り、tabindex="1"以上の値は使用せず、要素の配置やソースコードの順序を調整することで、自然なフォーカス順序を保つように努めるべきです。

実装例:カスタムコンポーネントや動的な要素でのTabindex管理

UIコンポーネント(例:タブ、モーダル、カルーセル、ドロップダウン)をJavaScriptで実装する場合、tabindexの適切な管理が特に重要になります。特定の要素が表示されているときだけフォーカス可能にしたり、コンポーネント内の要素に特別なキーボード操作(矢印キーなど)を実装したりする際にtabindex="-1"tabindex="0"を動的に切り替えることがあります。

例:簡単なタブUIでのTabindex管理

タブUIでは、現在選択されているタブパネル内のインタラクティブ要素のみをタブ順に含め、非表示のパネル内の要素はタブ順から除外するのが一般的なアクセシビリティパターンです。これにより、ユーザーがTabキーを押した際に、アクティブなコンテンツ内の要素だけにフォーカスが移動するようにします。

<div role="tablist">
  <button role="tab" aria-selected="true" aria-controls="panel1">タブ1</button>
  <button role="tab" aria-selected="false" aria-controls="panel2" tabindex="-1">タブ2</button>
  <button role="tab" aria-selected="false" aria-controls="panel3" tabindex="-1">タブ3</button>
</div>

<div id="panel1" role="tabpanel">
  <!-- タブ1のコンテンツ -->
  <p>これはタブ1の内容です。</p>
  <button>ボタンA</button>
</div>

<div id="panel2" role="tabpanel" hidden>
  <!-- タブ2のコンテンツ -->
  <p>これはタブ2の内容です。</p>
  <button>ボタンB</button>
</div>

<div id="panel3" role="tabpanel" hidden>
  <!-- タブ3のコンテンツ -->
  <p>これはタブ3の内容です。</p>
  <button>ボタンC</button>
</div>

JavaScriptでの制御(概要):

タブを切り替える際、JavaScriptで以下の処理を行います。

  1. 新しく選択されたタブボタンのaria-selectedtrueに、以前選択されていたタブボタンのaria-selectedfalseに設定します。
  2. 新しく選択されたタブボタンのtabindex0に、以前選択されていたタブボタンのtabindex-1に設定します。
  3. 新しく表示するタブパネルからhidden属性を削除し、以前表示されていたタブパネルにhidden属性を追加します。(またはCSSでdisplay: none;などを制御します)
  4. (必要であれば)新しく表示されたタブパネル内の最初の要素などにフォーカスを移動させます。

この例のように、JavaScriptと連携させてtabindexを動的に管理することで、複雑なUIコンポーネントでも論理的で使いやすいキーボードナビゲーションを実現できます。

テスト方法:キーボード操作での確認

tabindexの設定やキーボードナビゲーションが正しく機能しているかを確認するには、実際にキーボード操作でテストを行うことが最も重要です。

  1. TabキーとShift+Tabキー:

    • Webページの冒頭からTabキーを繰り返し押下し、すべてのインタラクティブな要素(リンク、ボタン、フォーム部品、tabindex="0"を指定した要素など)にフォーカスが順に移動するかを確認します。
    • フォーカスの移動順序が、ページの視覚的なレイアウトや操作の論理的な流れに沿っているかを確認します。
    • Shift+Tabキーを押下し、フォーカスが逆順に正しく移動するかを確認します。
    • tabindex="-1"を指定した要素にTabキーでフォーカスが移動しないことを確認します。
    • tabindex="1"以上の値を(非推奨ですが、もし使われている場合に)使用している要素が、他の要素よりも先に、値の小さい順にフォーカスされることを確認します(そして、それが意図した挙動であるか、管理可能かを検討します)。
  2. その他のキー:

    • 特定のコンポーネント(例: ラジオボタン、リストボックス、スライダー)では、Tabキーだけでなく矢印キーなどで内部を移動するパターンがあります。これらのキー操作も期待通りに機能するか確認します。
    • スペースキーやEnterキーで、フォーカスされているボタンやリンクが実行できるかを確認します。
  3. アクセシビリティ評価ツール:

    • Lighthouse、axe DevToolsなどの自動評価ツールも、一部のtabindexに関する問題を検出できます。ただし、フォーカスの「論理的な順序」は自動ツールだけでは判断できないため、手動でのキーボードテストは必須です。

まとめ

tabindex属性は、Webコンテンツのキーボードナビゲーションを制御するための強力なツールですが、特に正の整数値の使用には注意が必要です。最も安全でメンテナンスしやすい方法は、tabindex0または-1のみを使用し、要素のソースコード上の順序を適切に管理することです。

キーボードユーザーが迷うことなく、Webサイトやアプリケーションを快適に操作できるよう、tabindexを理解し、適切に活用することが、アクセシブルなWeb開発の重要な一歩となります。常に実際のキーボード操作で十分にテストを行い、ユーザーにとって論理的で使いやすいフォーカス順序が実現されているかを確認してください。