ARIA: tab ロール
ARIA のタブ (tab
) ロールは、タブリスト (tablist
) 内のインタラクティブな要素を示し、アクティブ化されると、関連するタブパネル (tabpanel
) を表示します。
<button role="tab" aria-selected="true" aria-controls="tabpanel-id" id="tab-id">
Tab label
</button>
説明
タブ (tab
) ロールを持つ要素は、タブパネル (tabpanel
) ロールに関連付けられた要素の可視性を制御します。 一般的なユーザーエクスペリエンスのパターンは、コンテンツ領域の上または横にある視覚的なタブのグループであり、別のタブを選択すると、コンテンツが変更され、選択したタブが他のタブよりも目立つようになります。
タブ (tab
) ロールを持つ要素は、タブリスト (tablist
) ロールを持つ要素の子であるか、タブリスト (tablist
) の aria-owns
プロパティの id
部分を持っている必要があります。 この組み合わせは、要素が関連要素のグループの一部であることを支援技術に識別させます。 一部の支援技術は、タブリスト (tablist
) 内のタブ (tab
) ロール要素の数を数えて、現在ターゲットにしているタブ (tab
) をユーザーに通知します。 これらには、タブパネル (tabpanel
) ロールを持つ要素を識別する aria-controls
プロパティが含まれているべきです。 タブパネル (tabpanel
) ロールを持つ要素にフォーカスがある場合、またはその子にフォーカスがある場合、タブ (tab
) ロールを持つ接続された要素がタブリスト (tablist
) 内のアクティブなタブであることを示します。
タブ (tab
) ロールを持つ要素を操作する場合、要素が選択されているかアクティブになっているときは、aria-selected
属性を true
に設定するべきです。 それ以外の場合は、false
に設定するべきです。 タブ (tab
) が選択されているかアクティブになっている場合、その制御されたタブパネル (tabpanel
) では、aria-expanded
属性を true
に設定し、hidden
属性 を false
に設定するべきです。 それ以外の場合は、その逆になります。
関連するロールと属性
- aria-selected
-
ブール値
- aria-controls
-
タブパネル (
tabpanel
) ロールを持つ要素のid
- id
-
コンテンツ
キーボードインタラクション
キー | アクション |
---|---|
Tab | フォーカスがタブリスト (tablist ) の外にある場合、フォーカスをアクティブなタブに移動します。 フォーカスがアクティブなタブにある場合、フォーカスをキーボードフォーカスの順序の次の要素、理想的にはアクティブなタブに関連付けられたタブパネル (tabpanel ) に移動します。 |
→ | タブリストの次のタブにフォーカスし、任意でアクティブ化します。 現在のタブがタブリストの最後のタブである場合、最初のタブをアクティブ化します。 |
← | タブリストの前のタブにフォーカスし、任意でアクティブ化します。 現在のタブがタブリストの最初のタブである場合、最後のタブをアクティブ化します。 |
Delete | 許可されている場合、現在選択されているタブをタブリストから削除します。 |
必要な JavaScript 機能
メモ: JavaScript を使用せずにタブのような機能を構築する方法はありますが、コンテンツを含むアクセス可能なタブに上記で必要とされるのと同じ機能のセットを提供する HTML と CSS のみの代替の組み合わせはありません。
例
この例では、タブ (tab
) ロールとタブリスト (tablist
) 、そして要素とタブパネル (tabpanel
) を組み合わせて、タブ付きコンテンツのインタラクティブなグループを作成します。 ここでは、コンテンツのグループを div
で囲んでいます。 タブリスト (tablist
) には、支援技術用にラベルを付けるための aria-label
があります。 各タブ (tab
) は、前述の属性を持つボタン (button
) です。 最初のタブ (tab
) には tabindex=0
があり、後で aria-selected=true
のタブに変更します。 すべてのタブパネル (tabpanel
) 要素には Tab 可能にするために tabindex=0
があり、現在アクティブな要素を除くすべてに hidden
属性があって、これは JavaScript で変更されます。 ボタンのスタイルを変更し、タブ (tab
) 要素の z-index
を変更して、アクティブな要素のタブパネル (tabpanel
) に接続しているように見せたり、非アクティブな要素がアクティブなタブパネル (tabpanel
) の後ろにあるように見せたりする基本的なスタイルが適用されます。
<div class="tabs">
<div role="tablist" aria-label="Sample Tabs">
<button
role="tab"
aria-selected="true"
aria-controls="panel-1"
id="tab-1"
tabindex="0">
First Tab
</button>
<button
role="tab"
aria-selected="false"
aria-controls="panel-2"
id="tab-2"
tabindex="-1">
Second Tab
</button>
<button
role="tab"
aria-selected="false"
aria-controls="panel-3"
id="tab-3"
tabindex="-1">
Third Tab
</button>
</div>
<div id="panel-1" role="tabpanel" tabindex="0" aria-labelledby="tab-1">
<p>Content for the first panel</p>
</div>
<div id="panel-2" role="tabpanel" tabindex="0" aria-labelledby="tab-2" hidden>
<p>Content for the second panel</p>
</div>
<div id="panel-3" role="tabpanel" tabindex="0" aria-labelledby="tab-3" hidden>
<p>Content for the third panel</p>
</div>
</div>
JavaScript でやるべきことは 2 つあります。 右矢印と左矢印を使用してタブ (tab
) 要素のフォーカスとタブインデックスを変更する必要があります。 また、タブ (tab
) をクリックしたときにアクティブなタブ (tab
) とタブパネル (tabpanel
) を変更する必要があります。
最初のことを達成するために、タブリスト (tablist
) でキーダウン (keydown
) イベントをリッスンします。 イベントの keyCode
が右矢印の 39 や左矢印の 37 の場合、イベントに反応します。 まず、現在のタブ (tab
) 要素の tabindex
を -1 に設定して、Tab 不可能にします。 次に、右矢印が押されている場合は、タブフォーカスカウンターを 1 つ増やします。 カウンターがタブ (tab
) 要素の数よりも大きい場合は、そのカウンターを 0 に設定して、最初のタブに戻ります。 左矢印が押されている場合は、タブフォーカスカウンターを 1 つ減らし、0 未満の場合、タブ (tab
) 要素の数から 1 を引いた数に設定します(最後の要素に到達するため)。 最後に、タブフォーカスカウンターと等しいインデックスのタブ (tab
) 要素にフォーカスを設定し、 tabindex
を 0 に設定して Tab 可能にします。
アクティブなタブ (tab
) とタブパネル (tabpanel
) の変更を処理するために、イベントを受け取り、イベントをトリガーした要素、トリガーした要素の親要素、およびその祖父母要素を取得する関数があります。 次に、親要素内で aria-selected=true
を持つすべてのタブを検索し、それを false
に設定してから、トリガーした要素の aria-selected
を true
に設定します。 その後、祖父母要素内のすべてのタブパネル (tabpanel
) 要素を見つけてすべて hidden
にし、最後に、トリガーしたタブ (tab
) の aria-controls
と等しい id
の要素を選択して、hidden
属性を削除して表示します。
window.addEventListener("DOMContentLoaded", () => {
const tabs = document.querySelectorAll('[role="tab"]');
const tabList = document.querySelector('[role="tablist"]');
// 各タブに click イベントハンドラーを追加します
tabs.forEach((tab) => {
tab.addEventListener("click", changeTabs);
});
// タブリストのタブ間の矢印ナビゲーションを有効にします
let tabFocus = 0;
tabList.addEventListener("keydown", (e) => {
// 右に移動
if (e.keyCode === 39 || e.keyCode === 37) {
tabs[tabFocus].setAttribute("tabindex", -1);
if (e.keyCode === 39) {
tabFocus++;
// 最後にいる場合は、最初に移動します
if (tabFocus >= tabs.length) {
tabFocus = 0;
}
// 左に移動
} else if (e.keyCode === 37) {
tabFocus--;
// 最初にいる場合は、最後に移動します
if (tabFocus < 0) {
tabFocus = tabs.length - 1;
}
}
tabs[tabFocus].setAttribute("tabindex", 0);
tabs[tabFocus].focus();
}
});
});
function changeTabs(e) {
const target = e.target;
const parent = target.parentNode;
const grandparent = parent.parentNode;
// タブから現在すべての選択状態を取り除きます
parent
.querySelectorAll('[aria-selected="true"]')
.forEach((t) => t.setAttribute("aria-selected", false));
// このタブを選択されたタブとして設定します
target.setAttribute("aria-selected", true);
// すべてのタブパネルを非表示にします
grandparent
.querySelectorAll('[role="tabpanel"]')
.forEach((p) => p.setAttribute("hidden", true));
// 選択されたパネルを表示します
grandparent.parentNode
.querySelector(`#${target.getAttribute("aria-controls")}`)
.removeAttribute("hidden");
}
ベストプラクティス
自分で追加する必要はなく、代わりに、組み込みの機能的でアクセス可能な機能のために、ボタン (button
) 要素をタブ (tab
) ロールと一緒に使用することをお勧めします。 タブ (tab
) ロールを持つ要素の Tab キー機能を制御するには、すべての非アクティブ要素を tabindex=-1
に設定し、アクティブ要素を tabindex=0
に設定することをお勧めします。
仕様書
Specification |
---|
Accessible Rich Internet Applications (WAI-ARIA) # tab |
Unknown specification |
優先順位
関連するプロパティは何ですか。 また、この属性やプロパティはどのような順序で読み取られますか(どのプロパティがこのプロパティよりも優先され、どのプロパティが上書きされますか)。
スクリーンリーダーのサポート
TBD
- WAI-ARIA ロール
alertdialog ロールの使用
ARIA: alert ロール
ARIA: application ロール
ARIA: article ロール
ARIA: banner ロール
ARIA: button ロール
ARIA: cell ロール
ARIA: checkbox ロール
ARIA: complementary ロール
ARIA: contentinfo ロール
ARIA: dialog ロール
ARIA: document ロール
ARIA: feed ロール
ARIA: figure ロール
ARIA: form ロール
ARIA: generic ロール
ARIA: grid ロール
ARIA: gridcell ロール
ARIA: heading ロール
ARIA: img ロール
ARIA: list ロール
ARIA: listbox ロール
ARIA: listitem ロール
ARIA: main ロール
ARIA: navigation ロール
ARIA: none ロール
ARIA: option ロール
ARIA: radio ロール
ARIA: region ロール
ARIA: row ロール
ARIA: rowgroup ロール
ARIA: search ロール
ARIA: spinbutton ロール
ARIA: switch ロール
ARIA: tab ロール
ARIA: table ロール
ARIA: term ロール
ARIA: textbox ロール
ARIA: tooltip ロール
group ロールの使用
link ロールの使用
log ロールの使用
presentation ロールの使用
progressbar ロールの使用
slider ロールの使用
status ロールの使用
toolbar ロールの使用