Video examples

iOS Voiceover Safari

Windows Jaws Chrome

Windows NVDA Chrome

MacOS Voiceover Safari

Code examples

Use as much semantic HTML as possible

This semantic HTML contains all accessibility features by default, and only requires the addition of role="switch".

  <legend>Activate your options:</legend>
  <input type="checkbox" role="switch" id="alphaSwitch">
  <label for="alphaSwitch">Alpha</label>

  <input type="checkbox" role="switch" id="bravoSwitch">
  <label for="bravoSwitch">Bravo</label>

  <input type="checkbox"
  <label for="charlieSwitch">Charlie</label>
Activate your options:

You can also use a button

This <button> toggle has focus and keyboard criteria built in. It requires the addition of role="switch" and scripting to toggle aria-checked="true/false".

<button role="switch" aria-checked="true">

When you can’t use semantic HTML

This custom switch requires extra attributes and keyboard event listeners.

<div role="switch" tabindex="0" aria-checked="true">

Developer notes


  • label text should describe the input.
  • Use aria-describedby="hint-id" for hints or additional descriptions
  • aria-label="Switch purpose" can also be used (as a last resort)


  • Use role="switch"


  • Semantic HTML
    • <fieldset> should wrap a switch group
    • <legend> should describe the group’s purpose
    • Each <label> must include for="input-id" to be associated with its input
  • Custom elements
    • Use role="group" in the palace of fieldset
    • Use aria-labelledby="label-id" to associate an element as a label
    • aria-label="Group purpose" can also be used if there’s no label with an ID


  • Semantic HTML
    • Use checked for native HTML
    • Use the disabled state for inactive switches
  • Custom element
    • Use aria-checked="true/false" to express state
    • Use aria-disabled="true" to declare inactive elements
    • Use aria-readonly="true" to declare a switch can’t be edited


  • Focus must be visible