The HTML aria-multiselectable attribute
Set aria-multiselectable="true" on a custom listbox, grid, tree or tablist when the user can select more than one item. It sits on the container, while each item carries aria-selected. For a form field, <select multiple> gives you this with no ARIA or script.
Overview
The aria-multiselectable property says the user may select more than one of a widget's selectable descendants. A grid, listbox, tablist or tree can take it directly, and a treegrid inherits it. The default, false, allows one item at a time.
A <select> with the multiple attribute is already exposed as aria-multiselectable="true", and ARIA in HTML advises against adding aria-multiselectable to a <select> yourself.
Browsers settle a mismatch differently. Firefox keeps the native state. Chrome reports the attribute on a list box, so <select size="3"> with it set to true is exposed as multi-selectable yet still takes one choice. A drop-down <select> doesn't expose it in either browser.
On a custom widget, the property works with aria-selected. Selected descendants should have aria-selected set to true and selectable ones false, and descendants that can't be selected should not use it at all.
A tab list is the odd case, because several panels can show at once. In a multi-selectable tablist, the tabs should also carry aria-expanded, true when a tab's panel is visible and false when it's hidden.
Syntax
<ul role="listbox" aria-label="Toppings" tabindex="0"
aria-multiselectable="true" aria-activedescendant="olives">
<li id="olives" role="option" aria-selected="true">Olives</li>
<li id="peppers" role="option" aria-selected="false">Peppers</li>
</ul>
Values
| Value |
|---|
| true | false |
Example
<p style="margin:0 0 8px">Pick your toppings. Click an option, or focus the list, use the Up and Down arrow keys and press Space.</p>
<ul id="toppings" role="listbox" tabindex="0" aria-label="Pizza toppings" aria-multiselectable="true" aria-activedescendant="olives" style="list-style:none;margin:0 0 8px;padding:4px;max-width:260px;border:1px solid #767676;border-radius:6px">
<li id="olives" role="option" aria-selected="true" style="padding:2px 6px;background:#d9e8fb;font-weight:bold">Olives</li>
<li id="peppers" role="option" aria-selected="false" style="padding:2px 6px">Peppers</li>
<li id="onions" role="option" aria-selected="true" style="padding:2px 6px;background:#d9e8fb;font-weight:bold">Onions</li>
<li id="basil" role="option" aria-selected="false" style="padding:2px 6px">Basil</li>
</ul>
<p role="status" id="chosen" style="margin:0">2 selected: Olives, Onions.</p>
<script>
const list = document.getElementById('toppings');
const options = [...list.querySelectorAll('[role="option"]')];
let active = 0;
function report() {
const picked = options.filter(function (o) { return o.getAttribute('aria-selected') === 'true'; });
document.getElementById('chosen').textContent = picked.length + ' selected' + (picked.length ? ': ' + picked.map(function (o) { return o.textContent; }).join(', ') : '') + '.';
}
function toggle(option) {
const on = option.getAttribute('aria-selected') !== 'true';
option.setAttribute('aria-selected', String(on));
option.style.background = on ? '#d9e8fb' : '';
option.style.fontWeight = on ? 'bold' : '';
report();
}
function move(index) {
active = index;
list.setAttribute('aria-activedescendant', options[index].id);
options.forEach(function (o, i) { o.style.outline = i === index ? '2px solid #1e72e0' : ''; });
}
list.addEventListener('focus', function () { move(active); });
list.addEventListener('blur', function () { options[active].style.outline = ''; });
options.forEach(function (option, index) {
option.addEventListener('click', function () { move(index); toggle(option); });
});
list.addEventListener('keydown', function (event) {
if (event.key === 'ArrowDown') move((active + 1) % options.length);
else if (event.key === 'ArrowUp') move((active - 1 + options.length) % options.length);
else if (event.key === ' ') toggle(options[active]);
else return;
event.preventDefault();
});
</script>
Best practices
- With
aria-multiselectable, say how to pick several items, such as by holding the Control key. - Writing false on a single-choice widget adds no meaning, because an explicit false and the implied default are the same.
- Consider a group of checkboxes when a
<select multiple>can't be styled the way you need. An <input type="checkbox"> is semantic, focusable and free to style. - Manage focus inside a custom listbox. A tabindex on the items or aria-activedescendant on the list can do it.























