Skip to content

Custom checkboxes and switches need a name

  • Rule: axe/aria-toggle-field-name
  • Checks: ARIA toggle fields must have an accessible name
  • WCAG: 4.1.2
  • Fix class: content: A fix needs authored text.
  • People who use a screen reader or a braille display, most of them blind.
  • People who control the page by speaking.

The label text sits beside the control, outside the element with the role

Section titled “The label text sits beside the control, outside the element with the role”

Give the text an id and point the control’s aria-labelledby at it, or move the text inside the element. Make clicking the text toggle the control too, as a native label would.

<div role="checkbox" tabindex="0" aria-checked="false" aria-labelledby="gift-label" class="checkbox"></div>
<span id="gift-label">This order is a gift</span>

Options in a custom list show only a swatch or an image

Section titled “Options in a custom list show only a swatch or an image”

Name each option with aria-label, using the name the product or data gives it, such as the color’s name.

<span id="color-label">Color</span>
<div role="listbox" aria-labelledby="color-label" tabindex="0" aria-activedescendant="color-green">
<div role="option" id="color-green" aria-selected="true" aria-label="Forest green" class="swatch"></div>
<div role="option" id="color-navy" aria-selected="false" aria-label="Navy" class="swatch"></div>
</div>

A native checkbox or radio button would do the job

Section titled “A native checkbox or radio button would do the job”

Use <input type="checkbox"> or <input type="radio"> with a <label>, styled as the design needs. The label names the control and makes its text clickable, with no script.

<input type="checkbox" id="gift">
<label for="gift">This order is a gift</label>

Showing the state as the only text, such as a switch that reads “On” or “Off”

Section titled “Showing the state as the only text, such as a switch that reads “On” or “Off””

axe accepts the text as the name, but people then hear “On” with no word on what the switch controls. The state already comes from aria-checked.

Using a symbol as the name, such as a star character in each option of a rating

Section titled “Using a symbol as the name, such as a star character in each option of a rating”

Screen readers read out the character, not its meaning. Name each option for its value, such as “3 stars”.

The part of the fix that differs in React, in its syntax. The rest of the guidance holds.

A switch or checkbox component renders its label beside the element with the role

Section titled “A switch or checkbox component renders its label beside the element with the role”

Build the control on a <button type="button"> with the label inside it, which names it and brings Enter and Space, and set aria-checked from the component’s state. If the label must stay outside, give it an id from useId and point aria-labelledby at it.

function Switch({ label, checked, onChange }) {
return (
<button type="button" role="switch" aria-checked={checked} onClick={() => onChange(!checked)}>
{label}
</button>
);
}

axe-core’s documentation of the rule

CORA’s fix guidance adapts content from accessibility-agents, under the MIT License: see its notice.