The HTML aria-selected attribute
Use aria-selected to mark the chosen tab, listbox option, grid cell or row in a widget. A value of true means selected and false means selectable but not chosen. With no attribute, tabs and options default to false, while grid cells and rows default to not selectable.
Overview
The aria-selected state marks which items are selected in a composite widget such as a tab list or grid. The gridcell, option, row and tab roles carry it, and so do columnheader, rowheader and treeitem through inheritance.
Focus can stand in for selection. If no item in a widget is explicitly selected, assistive technology may treat selection as following keyboard focus. Once any item is explicitly selected, the user agent must not convey that implied selection.
In a tab list or listbox with no aria-selected at all, Chrome and Firefox report the focused item as selected. Mark one tab true, and a different tab is no longer reported as selected when it takes focus.
Missing and false are different answers. A false item can be selected but isn't, while the default, undefined, means the element isn't selectable at all. WAI-ARIA 1.2 gives tab and option an implicit false, so those two stay selectable with no attribute.
HTML has no tab element, but a plain list of choices can be a <select>. ARIA in HTML says authors should not use aria-selected on its <option> elements. With both present, HTML-AAM says to expose only the selected attribute's value. Firefox does, and Chrome's tree shows aria-selected instead.
Syntax
<div role="tablist" aria-label="Order details">
<button role="tab" aria-selected="true">Items</button>
<button role="tab" aria-selected="false">Shipping</button>
</div>
Values
| Value |
|---|
| true | false | undefined |
Example
<p style="margin:0 0 10px">Click a tab, or focus one and press the Left or Right arrow key.</p>
<div role="tablist" aria-label="Order details" style="display:flex;gap:6px">
<button type="button" role="tab" id="tab-items" aria-selected="true" aria-controls="panel-items" style="font-weight:bold;text-decoration:underline">Items</button>
<button type="button" role="tab" id="tab-shipping" aria-selected="false" aria-controls="panel-shipping" tabindex="-1">Shipping</button>
<button type="button" role="tab" id="tab-returns" aria-selected="false" aria-controls="panel-returns" tabindex="-1">Returns</button>
</div>
<div role="tabpanel" id="panel-items" aria-labelledby="tab-items" tabindex="0" style="padding:10px 0">Two notebooks and one pen.</div>
<div role="tabpanel" id="panel-shipping" aria-labelledby="tab-shipping" tabindex="0" style="padding:10px 0" hidden>Arrives in three business days.</div>
<div role="tabpanel" id="panel-returns" aria-labelledby="tab-returns" tabindex="0" style="padding:10px 0" hidden>Free returns within 30 days.</div>
<p role="status" id="state" style="margin:0">Items is selected.</p>
<script>
const tabs = [...document.querySelectorAll('[role="tab"]')];
function select(tab) {
tabs.forEach(function (item) {
const chosen = item === tab;
item.setAttribute('aria-selected', String(chosen));
item.tabIndex = chosen ? 0 : -1;
item.style.fontWeight = chosen ? 'bold' : 'normal';
item.style.textDecoration = chosen ? 'underline' : 'none';
document.getElementById(item.getAttribute('aria-controls')).hidden = !chosen;
});
tab.focus();
document.getElementById('state').textContent = tab.textContent + ' is selected, so aria-selected is true on it and false on the other two tabs.';
}
tabs.forEach(function (tab, index) {
tab.addEventListener('click', function () { select(tab); });
tab.addEventListener('keydown', function (event) {
const step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0;
if (step) select(tabs[(index + step + tabs.length) % tabs.length]);
});
});
</script>
Best practices
- Back
aria-selected="true"with a visual sign on the tab, because the attribute draws nothing itself. - Link each tab to its panel with aria-controls. In a single-selection tab list, each panel should stay hidden until its tab is selected.
- Keep aria-selected and aria-checked apart in a listbox. Both are valid on
option, but avoid using both in one listbox unless each has its own meaning and its own control. - To select a whole grid column, set the value on each of its cells, since browsers must not spread it down from a
columnheaderon their own.























