Video examples
iOS Voiceover
Android Talkback
Windows Jaws Chrome
Windows NVDA Chrome
MacOS Voiceover Safari
Code examples
Use semantic HTML
- This semantic HTML contains all accessibility features by default.
- It uses CSS pseudo attributes to create the checkbox indicator, no Javascript.
<fieldset>
<legend>Choose your favorite NATO letters:</legend>
<input type="checkbox" id="alphaCheckbox">
<label for="alphaCheckbox">Alpha</label>
<input type="checkbox" id="bravoCheckbox">
<label for="bravoCheckbox">Bravo</label>
<input type="checkbox"
id="charlieCheckbox"
aria-describedby="charlieCheckboxDescription"
checked>
<label for="charlieCheckbox">Charlie</label>
<div class="description" id="charlieCheckboxDescription">
Charlie is everyone's favorite
</div>
</fieldset>
Don’t put interactive elements inside the label
Even though this is valid HTML, it creates unpredictable results with screenreaders. A (currently) reliable method is to keep interactive elements outside the label and reference it with aria-describedby="description-id"
<fieldset>
<legend>Legal disclaimers</legend>
<div id="description-tc" class="description-checkbox">
<a href="/code-of-conduct/">Read terms and conditions</a>
</div>
<input type="checkbox"
id="tc-agree"
aria-describedby="description-tc">
<label for="tc-agree">
I agree to the terms and conditions
</label>
</fieldset>
Fully disabled checkbox
- An input using
disabled
will not be focusable with the tab key - Arrow keys will still be able to browse disabled inputs
<fieldset>
<legend>Choose the starcrossed NATO letters</legend>
<input type="checkbox" id="romeoCheckbox" disabled checked>
<label for="romeoCheckbox">Romeo</label>
<input type="checkbox" id="julietCheckbox" disabled>
<label for="julietCheckbox">Juliet</label>
</fieldset>
Disabled and focusable checkbox
It’s possible to use aria-disabled="true"
so screen reader users can focus the checkbox. Use preventDefault()
to prevent the checkbox from being checked.
<fieldset>
<legend>Choose your favorite cities</legend>
<input type="checkbox" id="limaCheckbox" aria-disabled="true" checked>
<label for="limaCheckbox">Lima</label>
<input type="checkbox" id="quebecCheckbox" aria-disabled="true">
<label for="quebecCheckbox">Quebec</label>
</fieldset>
When you can’t use semantic HTML
This custom checkbox requires extra attributes and event listeners.
<div role="checkbox" tabindex="0" aria-checked="true">
Alpha
</div>
Speciality checkboxes
Sometimes a design may call for a card type checkbox.
- Its core should still be a semantic checkbox input
- Use
aria-describedby
to read extra content after the the name, role and state
<ul class="cards">
<li class="card interactive">
<input type="checkbox"
id="deltaCheckboxCard"
aria-describedby="descriptionDelta" >
<label for="deltaCheckboxCard">
Delta
</label>
<div class="extended-description"
id="descriptionDelta">
Delta (prounounced: <strong>dell</strong>-tah)
is the fourth letter of the NATO alphabet.
</div>
</li>
<li class="card interactive">
<input type="checkbox"
id="echoCheckboxCard"
aria-describedby="descriptionEcho" >
<label for="echoCheckboxCard">Echo</label>
<div class="extended-description"
id="descriptionEcho">
Echo (prounounced: <strong>eck</strong>-oh)
is the fifth letter of the NATO alphabet.
</div>
</li>
</ul>
-
Delta (prounounced: dell-tah) is the fourth letter of the NATO alphabet.
-
Echo (prounounced: eck-oh) is the fifth letter of the NATO alphabet.
Developer notes
Name
label
text must describe the checkbox input.- Use
aria-describedby="description-id"
for hints or additional descriptions aria-label="Checkbox input purpose"
can also be used (as a last resort)
Role
- By default, semantic HTML checkbox inputs identify as a checkbox
- Use
role="checkbox"
for custom elements
Group
- Semantic HTML
<fieldset>
wraps a checkbox group<legend>
describes the group’s purpose- Each
<label>
must includefor="input-id"
to be associated with its input
- Custom elements
- Use
role="group"
in the place 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
- Use
State
- Semantic HTML
- Use
checked
for native HTML - Use the
disabled
state for inactive checkboxes
- Use
- Custom element
- Use
aria-checked="true/false"
to express state - Use
aria-disabled="true"
to declare inactive elements
- Use
Focus
- Focus must be visible
- Custom elements will require keyboard event listeners