tablist
Marks a container as the strip of tabs in a tabbed interface. Holds role="tab" children. Tabs and tabpanels are an ARIA-only pattern — there is no native HTML tablist.
When to use
Around the row (or column) of role="tab" elements in a tabbed interface. The tablist MUST have an accessible name via aria-label or aria-labelledby — without it, a screen-reader user hearing “tab list” cannot tell which tablist on the page it is.
Vertical tab strips need aria-orientation="vertical". The default is horizontal, so omit the attribute for horizontal tabs.
If your “tabs” are really navigation to other URLs, use <nav> with <a> links instead — the URL-changes-on-click pattern does not match tablist semantics.
Keyboard + focus contract
Per the APG tabs pattern:
- Tab moves focus into the tablist and onto the selected tab; another Tab moves OUT (typically into the active tabpanel).
- Left/Right arrows move focus between tabs (Up/Down for vertical tablists). Wraparound is optional but conventional.
- Home / End jump to first / last tab.
- Activation: in automatic mode, arrow keys both move focus AND select. In manual mode (recommended when activation is expensive), Space or Enter selects the focused tab.
The tablist itself does not handle focus — focus goes onto the tab, not the tablist container.
Common failures
- Tablist with no accessible name. Multiple tablists on one page become indistinguishable.
- All tabs have
tabindex="0". The pattern is single-tab-stop; only the selected tab hastabindex="0". - Missing
aria-orientation="vertical"on a vertical tablist — the screen reader instructs users to use Left/Right when the visual layout demands Up/Down. role="tablist"wrapping links (<a href="#section">) instead of buttons. Anchor scroll-jumps the page and breaks the back button.- Tabpanel hidden via
display: noneANDhiddenattribute when one is enough.
Example
<div role="tablist" aria-label="Project sections" aria-orientation="horizontal">
<button role="tab" id="t-overview" aria-selected="true" aria-controls="p-overview" tabindex="0">Overview</button>
<button role="tab" id="t-files" aria-selected="false" aria-controls="p-files" tabindex="-1">Files</button>
<button role="tab" id="t-team" aria-selected="false" aria-controls="p-team" tabindex="-1">Team</button>
</div>