Switch
A switch is an input widget that allows users to choose one of two values: on or off. Switches are similar to checkboxes and toggle buttons, which can also serve as binary inputs, although both checkboxes and toggle buttons can have three states: on, off, or indeterminate. A switch's state is conveyed to assistive technology users as "checked" or "unchecked" so use a switch when these states will be meaningful to the user.
A switch may be implemented using a semantic HTML checkbox (recommended), a button element with role="switch"
or a
non-semantic element with role="switch"
.
Role
A switch widget must have a role of switch. This is achieved by adding the role="switch"
attribute to the element.
Even if the switch is implemented using a semantic HTML checkbox, the role="switch"
attribute must still be added.
Accessibility label
A switch must have an accessibility label. The accessibility label is the text that is read by screen readers to describe the element. There are many ways to provide an accessibility label for a switch. If an HTML checkbox is used, the accessibility label should be provided by the checkbox label. The accessibility label should convey the functionality of the switch but not the current state of the switch (On/Off).
1<!-- The checkbox label constitutes the switch's accessibility label -->2<label>3 Dark mode4 <input type="checkbox" role="switch" class="on" />5</label>67<!-- The `label[for]` attribute may also be used instead of wrapping8 the input in a label tag -->9<label for="dark-mode">10 Dark mode11</label>12<input type="checkbox" id="dark-mode" role="switch" class="on" />
If the switch is implemented using a button element or a non-semantic element, the accessibility label can be provided in a couple of ways:
1<!-- The button text constitutes the switch's accessibility label -->2<button role="switch" aria-checked="false">3 <span class="label">Dark mode</span>4 <span class="on" aria-hidden="true">On</span>5 <span class="off" aria-hidden="true">Off</span>6</button>78<!-- Switch gets its accessibility label from the aria-label attribute -->9<div role="switch" tabindex="0" aria-label="Dark mode" aria-checked="false">10 <span class="on" aria-hidden="true">On</span>11 <span class="off" aria-hidden="true">Off</span>12</div>1314<!-- Switch gets its accessibility label from the aria-labelledby attribute -->15<span id="dark-mode-label">Dark mode</span>16<div role="switch" tabindex="0" aria-labelledby="dark-mode-label" aria-checked="false">17 <span class="on" aria-hidden="true">On</span>18 <span class="off" aria-hidden="true">Off</span>19</div>
Focus sequence
A switch must be focusable unless it is disabled. This is important for keyboard users who need to be able to navigate to the switch.
Semantic HTML inputs and buttons are always focusable when not disabled. Switches implemented using non-semantic elements
can be made focusable by adding the tabindex="0"
attribute to the switch element.
Disabled switches
A switch implemented using a checkbox or button element can be disabled by adding the disabled
attribute. In that case, the switch
will not be focusable.
Switches implemented using non-semantic elements can be disabled by adding the aria-disabled="true"
attribute to the switch element.
In that case the developer may choose to make the switch focusable or not. The aria-disabled
attribute should not be used
on a semantic HTML checkbox or button element.
1<!-- Disabled non-semantic HTML switch -->2<div role="switch" aria-label="Dark mode" aria-checked="false" aria-disabled="true">3 ...4</div>56<!-- Disabled non-semantic HTML switch that is focusable -->7<div role="switch" tabindex="0" aria-label="Dark mode" aria-checked="false" aria-disabled="true">8 ...9</div>1011<!-- Switches implemted using semantic elements should not use aria-disabled -->12✓ <button role="switch" aria-checked="false" disabled>...</button>13✓ <input type="checkbox" role="switch" class="on" disabled />14✗ <button role="switch" aria-checked="false" aria-disabled="true">...</button>15✗ <input type="checkbox" role="switch" class="on" aria-disabled="true" />
Forbidden interactive children
A switch must not contain any interactive children such as links or buttons. Such children would be inaccessible to screen reader users since they will be excluded from the accessibility tree.
Toggle activation
Conveying the state of the switch
When a switch is activated, its state changes from On to Off or vice versa. The state of the switch must be conveyed to screen reader users.
This can be done by updating the aria-checked
attribute to reflect the new state of the switch.
The aria-checked
attribute must be set to either true
or false
.
1<!-- Switch is initially Off -->2<div3 id="dark-mode-switch"4 role="switch"5 tabindex="0"6 aria-label="Dark mode"7 aria-checked="false"8 class="off"9/>
1function toggleSwitch(switchElement) {2 const isDisabled = switchElement.getAttribute('aria-disabled') === 'true';3 if (isDisabled) {4 // Do nothing if switch is disabled5 return;6 }7 const currentState = switchElement.getAttribute('aria-checked');8 if currentState == 'false' {9 switchElement.classList.add('on');10 switchElement.classList.remove('off');11 switchElement.setAttribute('aria-checked', 'true');12 } else {13 switchElement.classList.add('off');14 switchElement.classList.remove('on');15 switchElement.setAttribute('aria-checked', 'false');16 }17}
Keyboard activation
A switch must be able to be activated using the keyboard. This is important for keyboard users who need to be able to toggle the switch.
This can be achieved by adding a keyup
event listener to the switch element. The event listener should check for the Enter
and Space
keys.
1const switchElement = document.getElementById('dark-mode-switch');2switchElement.addEventListener('click', () => toggleSwitch(switchElement));3switchElement.addEventListener('keyup', (event) => {4 if (event.key === 'Enter' || event.key === ' ') {5 toggleSwitch(switchElement);6 }7});
Toggle activation test
The toggle activation test checks that the switch can be activated by both mouse and keyboard.
It also tests that when activated, the aria-checked
attribute is updated to reflect the new
state of the switch. The test uses the aria-checked
attribute to verify that
the state of the switch changes for each activation method.
It runs three times to test activation using the mouse, the Enter
key and the Space
key.
In the case of an HTML checkbox input, the test will fail if the checkbox element includes
the aria-checked
attribute since a native HTML checkbox should only use the checked
attribute. The rest of the toggle activation test is skipped since keyboard activation and
updating the checked
attribute is handled by the browser.
For switches that are not implemented using a native HTML checkbox, the test will check
that for disabled switches (aria-disabled="true"
), their state does not changed when
clicked or activated using the keyboard.