References

Beginner-friendly references for web development, with live, editable examples.

The HTML aria-checked attribute

ARIA Accessibility
In short

The aria-checked attribute reports whether a custom checkbox, radio button or switch is checked. A script sets true or false on every toggle, or mixed for a partly checked checkbox. ARIA in HTML forbids it on checkbox and radio inputs, which have a native state.

Overview

The aria-checked attribute is an ARIA state saying whether a widget is checked, unchecked or partly checked. It goes on an element with a checkable role, such as <div role="checkbox">. On other roles, browsers are required to ignore it.

Authors must give it a value on five roles, which are checkbox, switch, radio, menuitemcheckbox and menuitemradio. The option role supports it without requiring it, and treeitem inherits it. A checkbox role with no aria-checked is exposed as unchecked.

The mixed value says a control stands for a group whose items are a mix of checked and unchecked, such as a Select all box with only some boxes checked. It's defined for the checkbox and menuitemcheckbox roles. On radio, menuitemradio and switch, browsers must treat mixed as false.

No behavior comes with the attribute. A click or the Space key on a role="checkbox" element leaves aria-checked as it was, so a script has to change the value and the look of the control.

A native checkbox or radio input updates its own state. Use its checked attribute, with the indeterminate property for mixed, since aria-checked isn't allowed on checkbox and radio inputs. That covers <input type="checkbox" role="switch"> too, where checked serves the switch role.

Syntax

<div role="checkbox" tabindex="0" aria-checked="mixed">All extras</div>
<div role="switch" tabindex="0" aria-checked="true">Dark mode</div>

Values

Value
true | false | mixed | undefined

Example

Live example
<div role="group" aria-label="Pizza extras">
  <div id="all" role="checkbox" tabindex="0" aria-checked="false"><span aria-hidden="true">[ ] </span>All extras</div>
  <div style="margin-left:24px">
    <div class="item" role="checkbox" tabindex="0" aria-checked="false"><span aria-hidden="true">[ ] </span>Olives</div>
    <div class="item" role="checkbox" tabindex="0" aria-checked="false"><span aria-hidden="true">[ ] </span>Mushrooms</div>
    <div class="item" role="checkbox" tabindex="0" aria-checked="false"><span aria-hidden="true">[ ] </span>Peppers</div>
  </div>
</div>
<p id="out" role="status"></p>
<p>Click a box, or press Space on it, and watch All extras change.</p>
<script>
const all = document.getElementById('all');
const items = [...document.querySelectorAll('.item')];
const out = document.getElementById('out');
const marks = { true: '[x] ', false: '[ ] ', mixed: '[-] ' };
function paint() {
  const on = items.filter(i => i.getAttribute('aria-checked') === 'true').length;
  all.setAttribute('aria-checked', on === 0 ? 'false' : on === items.length ? 'true' : 'mixed');
  [all, ...items].forEach(box => { box.firstElementChild.textContent = marks[box.getAttribute('aria-checked')]; });
  out.textContent = 'All extras has aria-checked="' + all.getAttribute('aria-checked') + '", with ' + on + ' of 3 checked.';
}
function toggle(box) {
  if (box === all) {
    const next = all.getAttribute('aria-checked') === 'true' ? 'false' : 'true';
    items.forEach(i => i.setAttribute('aria-checked', next));
  } else {
    box.setAttribute('aria-checked', box.getAttribute('aria-checked') === 'true' ? 'false' : 'true');
  }
  paint();
}
[all, ...items].forEach(box => {
  box.addEventListener('click', () => toggle(box));
  box.addEventListener('keydown', e => {
    if (e.key === ' ') { e.preventDefault(); toggle(box); }
  });
});
paint();
</script>

Best practices

  • Make an aria-checked checkbox or switch work from the keyboard. Add tabindex="0" so it can take focus, and toggle it on the Space key, the expected key for a checkbox.
  • Allow only one checked radio per group. When a new radio is checked, the old one's aria-checked becomes false, and your script is what sets it.
  • Base the check mark on the attribute's current value, in script or with a selector such as [aria-checked="mixed"], so the two can't disagree.
  • Add a visible focus style to each custom checkbox or switch.
  • Use the switch role for on and off settings. It offers about the same function as a checkbox and lets assistive technology present the widget in a way that fits how it looks.

Frequently asked questions

What values does aria-checked take?
The aria-checked attribute takes true, false, mixed or undefined. Undefined is the default, and it means the element doesn't support being checked, though browsers should treat a checkbox role with no value as unchecked.
Can a button take aria-checked?
No, a toggle button takes aria-pressed, because the button role doesn't support aria-checked. A button element can take the switch role instead, which does support aria-checked.
Can aria-checked override a native checkbox?
No, a plain checkbox or radio input keeps its native state whatever aria-checked says. With role=switch, though, Firefox exposes an unchecked box with aria-checked=true as checked.
How do I make a native checkbox partly checked without aria-checked?
Set the indeterminate property from script instead of aria-checked=mixed. The property maps to the mixed state, so the box is exposed as partly checked.
Is aria-checked sent when a form is submitted?
No, aria-checked isn't form data, and a div with role=checkbox adds nothing to FormData. A custom checkbox needs more script to send a name and a value with the form.
How does JavaScript read aria-checked?
JavaScript gets aria-checked from getAttribute or the ariaChecked property. Both give the string value, and null when the attribute is missing.
Can a role=option element use aria-checked?
Yes, the option role supports aria-checked alongside aria-selected. That goes beyond a native select element, whose options can only be selected.