aria-selected and Tab Patterns
Implement keyboard-accessible tab interfaces.
aria-selected and Tab Patterns is a free HTML Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the HTML Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Tab Pattern Overview
A tab interface has three ARIA components:
role="tablist"— container for all tabsrole="tab"— individual tab buttonrole="tabpanel"— the content panel for each tab
ARIA Tab Structure
Complete accessible tab markup:
<div role="tablist" aria-label="Account Settings">
<button role="tab" id="tab-1" aria-selected="true"
aria-controls="panel-1">Profile</button>
<button role="tab" id="tab-2" aria-selected="false"
aria-controls="panel-2" tabindex="-1">Security</button>
<button role="tab" id="tab-3" aria-selected="false"
aria-controls="panel-3" tabindex="-1">Notifications</button>
</div>
<div id="panel-1" role="tabpanel" aria-labelledby="tab-1">
Profile content...
</div>
<div id="panel-2" role="tabpanel" aria-labelledby="tab-2" hidden>
Security content...
</div>aria-selected
aria-selected indicates the currently active item in a selection context:
<!-- In a tablist: -->
<button role="tab" aria-selected="true">Active Tab</button>
<button role="tab" aria-selected="false">Other Tab</button>
<!-- In a listbox: -->
<ul role="listbox">
<li role="option" aria-selected="false">Option 1</li>
<li role="option" aria-selected="true">Option 2</li>
</ul>Tab Keyboard Pattern
ARIA patterns define specific keyboard behavior for tabs:
- Tab — moves focus into the tablist to the selected tab
- Arrow keys — cycle between tabs
- Tab again — moves focus out of tablist into active panel
- Home — first tab
- End — last tab
Tab Keyboard Implementation
Keyboard navigation for tabs using arrow keys:
const tabs = document.querySelectorAll('[role="tab"]');
tabs.forEach((tab, i) => {
tab.addEventListener('keydown', (e) => {
let target;
if (e.key === 'ArrowRight') target = tabs[(i + 1) % tabs.length];
if (e.key === 'ArrowLeft') target = tabs[(i - 1 + tabs.length) % tabs.length];
if (e.key === 'Home') target = tabs[0];
if (e.key === 'End') target = tabs[tabs.length - 1];
if (target) {
activateTab(target);
target.focus();
}
});
});activateTab Function
Function to switch tabs and update ARIA:
function activateTab(selectedTab) {
// Deactivate all tabs:
document.querySelectorAll('[role="tab"]').forEach(tab => {
tab.setAttribute('aria-selected', 'false');
tab.setAttribute('tabindex', '-1');
document.getElementById(tab.getAttribute('aria-controls')).hidden = true;
});
// Activate selected tab:
selectedTab.setAttribute('aria-selected', 'true');
selectedTab.setAttribute('tabindex', '0');
document.getElementById(selectedTab.getAttribute('aria-controls')).hidden = false;
}Roving tabindex Pattern
Tab groups use roving tabindex to keep one tab in the tab order:
<!-- Only the selected tab has tabindex=0 -->
<button role="tab" aria-selected="true" tabindex="0">Active</button>
<button role="tab" aria-selected="false" tabindex="-1">Other</button>
<button role="tab" aria-selected="false" tabindex="-1">Another</button>
<!-- When user arrows to a new tab:
1. Set new tab tabindex=0
2. Set old tab tabindex=-1
3. Focus new tab -->aria-selected vs aria-checked
aria-selected vs aria-checked — different contexts:
aria-selected— used in selection widgets: tabs, options in listbox, items in treearia-checked— used in checkable items: checkboxes, menu items with checkmark
Tabpanel Focus
When a tab is activated, the panel becomes visible but focus stays on the tab:
// Users can then Tab to move into the panel content
// The panel should not automatically receive focus
// Exception: if the panel is very long, consider moving focus
// to the panel heading for long-form content tabs
// Panel should have tabindex=-1 for programmatic focus:
<div id="panel-1" role="tabpanel" aria-labelledby="tab-1" tabindex="-1">Automatic vs Manual Activation
Two tab activation models:
- Automatic — tabs activate as the user arrows through them (simpler UX)
- Manual — user must press Enter/Space to activate after arrowing (better when tab content requires loading)
Accessible Tab Styling
CSS for accessible tab selected state:
[role="tab"] {
border-bottom: 3px solid transparent;
padding: 0.75rem 1rem;
cursor: pointer;
}
[role="tab"][aria-selected="true"] {
border-bottom-color: #0070f3;
font-weight: bold;
}
/* :focus-visible for keyboard users: */
[role="tab"]:focus-visible {
outline: 2px solid #0070f3;
outline-offset: -2px;
}Quick Check
How should keyboard navigation work within a tab list?
Recap: aria-selected and Tabs
Tab pattern essentials:
- tablist → tab (aria-selected) → tabpanel (aria-labelledby)
- Arrow keys navigate between tabs; Tab enters the panel
- Roving tabindex: only active tab has tabindex=0
- aria-selected="true" on the active tab
- Inactive panels use hidden attribute
Frequently asked questions
Is the “aria-selected and Tab Patterns” lesson free?
Yes — the full text of “aria-selected and Tab Patterns” is free to read here on the web, and the HTML Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the HTML Academy course, upgrade to CoddyKit PRO.
What will I learn in “aria-selected and Tab Patterns”?
Implement keyboard-accessible tab interfaces. You practise HTML Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start HTML Academy?
No prior experience is required. HTML Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “aria-selected and Tab Patterns” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this HTML Academy lesson?
Yes. Every HTML Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- aria-expanded aria-controls for Toggles
- aria-selected and Tab Patterns
- Live Regions aria-live aria-atomic aria-relevant
- Testing with Screen Readers