Standards · ARIA

Role Widget

switch

Marks an element as an on/off switch. Functionally close to a checkbox, but announced as "switch, on" or "switch, off" rather than "checked" — better matches a settings toggle. There is no native HTML equivalent yet.

When to use

For a binary settings control where “on” and “off” describe the state better than “checked” and “unchecked” — Wi-Fi, dark mode, notifications, airplane mode. There is no native HTML switch element, so you have two valid approaches:

  1. <button type="button" role="switch" aria-checked="false"> — preferred, because you inherit native button focus and activation.
  2. <input type="checkbox" role="switch"> — also acceptable; form submission still works, and the role override changes how assistive tech announces it.

Do not use role="switch" for things that aren’t truly binary. If the action navigates, opens a menu, or starts a process, use button or link.

Keyboard + focus contract

Per the APG switch pattern:

  • Tab moves focus to the switch.
  • Space toggles aria-checked. Enter SHOULD also toggle (the APG recommends both, since users expect button-like behaviour from a button-based switch).
  • Focus stays on the switch after toggling.

aria-checked only takes "true" or "false" on a switch — "mixed" is invalid here.

Common failures

  • role="switch" without aria-checked on first render. The state is required.
  • aria-checked="mixed" on a switch. Only valid for checkbox.
  • Using aria-pressed instead of aria-checked. aria-pressed belongs on a toggle button (mute/unmute), where the button performs an action. A switch represents a setting state.
  • A switch that does not update aria-checked when toggled via CSS only.
  • Tiny switch hitboxes that fail WCAG 2.5.8 Target Size. The interactive area must reach 24x24 CSS pixels.

Example

<button
  type="button"
  role="switch"
  aria-checked="false"
  onclick="
    const next = this.getAttribute('aria-checked') === 'true' ? 'false' : 'true';
    this.setAttribute('aria-checked', next);
  "
>
  Dark mode
</button>