Video examples
iOS Voiceover
Android Talkback
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 radio indicator, no Javascript.
<fieldset>
<legend>
Choose the best NATO letter
</legend>
<input type="radio" name="nato" id="alphaRadio">
<label for="alphaRadio">Alpha</label>
<input type="radio" name="nato" id="bravoRadio">
<label for="bravoRadio">Bravo</label>
<input type="radio" name="nato" id="charlieRadio" aria-describedby="description-charlie" checked>
<label for="charlieRadio">Charlie</label>
<div class="description" id="description-charlie">The best at everything</div>
</fieldset>
Fully disabled radio inputs
<fieldset>
<legend>
Choose your favorite coffee chain
</legend>
<input type="radio" name="coffee" id="dunkinRadio">
<label for="dunkinRadio">Dunkin'</label>
<input type="radio" name="coffee" id="dutchRadio" checked>
<label for="dutchRadio">Dutch Brothers</label>
<input type="radio" name="coffee" id="starbucksRadio" disabled>
<label for="starbucksRadio">Starbucks</label>
</fieldset>
Disabled and focusable radio inputs
It’s possible to use aria-disabled="true"
so screen reader users can focus the radio button with the arrow keys. Use preventDefault()
to prevent the checkbox from being checked.
When specific radio inputs are conditionally enabled/disabled by other controls in the page this method can make ensure all radio input options are discoverable.
<fieldset>
<legend>
Choose your favorite dance
</legend>
<input type="radio" name="dance" id="carltonRadio" aria-disabled="true">
<label for="carltonRadio">Carlton</label>
<input type="radio" name="dance" id="foxtrotRadio">
<label for="foxtrotRadio">Foxtrot</label>
<input type="radio" name="dance" id="tangoRadio" checked>
<label for="tangoRadio">Tango</label>
</fieldset>
Required radio inputs
Ensuring all screenreaders indicate radio inputs as being required requires some aria and reinforcement.
- Use
aria-required="true"
to indicate the group is required - Use
aria-invalid="true/false"
to indicate an error state - Add
role="radiogroup"
to the<fieldset>
to make thearia-required
attribute valid - Add “Required” as text to the
<legend>
to ensure compliance across all platforms
<fieldset aria-required="true"
aria-invalid="true"
role="radiogroup">
<legend>
Choose your second favorite NATO letter <span>Required</span>
</legend>
<input type="radio" name="natoReq" id="deltaRadioReq">
<label for="deltaRadioReq">Delta</label>
<input type="radio" name="natoReq" id="echoRadioReq">
<label for="echoRadioReq">Echo</label>
<input type="radio" name="natoReq" id="foxtrotRadioReq">
<label for="foxtrotRadioReq">Foxtrot</label>
</fieldset>
Radio button cards
<ul class="cards">
<li class="card interactive">
<input type="radio"
name="radioCards"
id="deltaRadioCard"
aria-describedby="description-deltaRadioCard" >
<label for="deltaRadioCard">
Delta
</label>
<div class="extended-description"
id="description-deltaRadioCard">
Delta (prounounced: <strong>dell</strong>-tah)
is the fourth letter of the NATO alphabet.
</div>
</li>
<li class="card interactive">
<input type="radio"
name="radioCards"
id="echoRadioCard"
aria-describedby="description-echoRadioCard">
<label for="echoRadioCard">Echo</label>
<div class="extended-description"
id="description-echoRadioCard">
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.
When you can’t use semantic HTML
This custom button requires extra scripting work for roving tabindex and event listeners.
<custom-label id="labelId">
Which is your favorite NATO letter:
</custom-label>
<div role="radiogroup" aria-labelledby="labelId">
<custom-element role="radio" tabindex="-1">
Alpha
</custom-element>
<custom-element role="radio" tabindex="-1">
Bravo
</custom-element>
<custom-element role="radio" tabindex="-1">
Charlie
</custom-element>
</div>
Specialty use cases
Radio mixed with interactive elements
Avoid placing interactive elements between radio buttons.
- Radio button focus order is not what you think it is.
- When nothing is selected, tab order moves through as expected.
- However, as soon as a radio button is selected, the selected radio input receives focus first from the group.
Checkbox radio hack
- This hack must be used very carefully on a case by case basis.
- With great power comes great responsibility.
<fieldset class="checkbox-radio-group">
<legend>Choose your payment method:</legend>
<input class="radio"
type="checkbox"
role="radio"
name="checkboxRadioGroup"
id="checkboxRadioAlpha"
aria-describedby="editAlpha"
checked>
<label for="checkboxRadioAlpha">
Alpha
</label>
<button type="button"
class="tertiary"
id="editAlpha">
Edit
<span class="hidden">
payment method alpha
</span>
</button>
<input class="radio"
type="checkbox"
role="radio"
name="checkboxRadioGroup"
id="checkboxRadioBravo"
aria-describedby="editBravo">
<label for="checkboxRadioBravo">
Bravo
</label>
<button type="button"
class="tertiary"
id="editBravo">
Edit
<span class="hidden">
payment method Bravo
</span>
</button>
<input class="radio"
type="checkbox"
role="radio"
name="checkboxRadioGroup"
id="checkboxRadioCharlie"
aria-describedby="editCharlie">
<label for="checkboxRadioCharlie">
Charlie
</label>
<button type="button"
class="tertiary"
id="editCharlie">
Edit
<span class="hidden">
payment method Charlie
</span>
</button>
</fieldset>