Radio Buttons — Accessibility Specification

WCAG 2.1 AA • AODA compliant • Updated 2025-10-28


What is this component?

What is this component? A radio button (<input type="radio">) allows users to select exactly one option from a list. All radio buttons within the same group share the same name attribute, ensuring that only one can be selected at a time.

Where and how is it used? Common use cases include:

Accessibility Requirements

RequirementWCAG CriteriaDescription
Programmatic grouping 1.3.1 Info and Relationships (A) Use <fieldset> and <legend> to group related radios and provide a clear group name announced by screen readers.
Label association 3.3.2 Labels or Instructions (A) Each radio must have a clear, descriptive label associated via for/id or wrapping the input.
Keyboard operability 2.1.1 Keyboard (A) Users navigate between radios with arrow keys (/) and activate with Space. Focus moves with Tab between groups.
Focus visible 2.4.7 Focus Visible (AA) Provide a strong visual focus indicator around the selected or focused radio button.
Name, Role, Value 4.1.2 Name, Role, Value (A) Native radios expose role “radio,” name (from group legend/label), and state (checked/unchecked) automatically.

ARIA Roles and Attributes

ARIA Role/AttributeUsed OnPurpose & Usage
<input type="radio">Native radioPreferred element. Implicit role “radio”; exposes state and supports keyboard navigation.
role="radio"Custom elementsUsed only when recreating radios with div/spans. Must manage aria-checked, tabindex, arrow key navigation, and Space to toggle.
aria-checked="true|false"Custom radiosConveys the selected state of each radio. Only one per group should be “true.”
role="radiogroup"Container for custom radiosGroups related radios so screen readers announce one selection among many.
aria-labelledby / aria-labelCustom radiosGives accessible name when visible text is not directly associated.

Implementation Guidelines

<!-- Native radio buttons -->
<fieldset>
  <legend>Preferred contact method</legend>
  <label><input type="radio" name="contact" value="email"> Email</label>
  <label><input type="radio" name="contact" value="phone"> Phone</label>
  <label><input type="radio" name="contact" value="sms"> SMS</label>
</fieldset>

<!-- Custom radio group -->
<div role="radiogroup" aria-labelledby="rg1">
  <p id="rg1">Payment Method</p>
  <div role="radio" tabindex="0" aria-checked="true">Credit Card</div>
  <div role="radio" tabindex="-1" aria-checked="false">PayPal</div>
</div>
<script>
const radios = document.querySelectorAll('[role="radio"]');
radios.forEach((r, i) => r.addEventListener('keydown', e => {
 if(['ArrowDown','ArrowRight'].includes(e.key)) { e.preventDefault(); radios[(i+1)%radios.length].focus(); }
 if(['ArrowUp','ArrowLeft'].includes(e.key)) { e.preventDefault(); radios[(i-1+radios.length)%radios.length].focus(); }
 if(e.key===' '||e.key==='Spacebar') { radios.forEach(x=>x.setAttribute('aria-checked','false')); r.setAttribute('aria-checked','true'); }
}));
</script>

DO’s

Don’ts

Common Pitfalls

Testing Checklist

Test ItemWCAG CriteriaPass Criteria
Group Name Announced1.3.1 Info and Relationships (A)Screen reader announces legend or group label for radios.
Keyboard Navigation2.1.1 Keyboard (A)Tab moves between groups; arrow keys move within group; Space selects option.
Focus Visible2.4.7 Focus Visible (AA)Focus indicator clearly visible on focused radio.
State Announcement4.1.2 Name, Role, Value (A)AT announces “selected” and “not selected” states correctly.
Single Selection3.3.2 Labels/Instructions (A)Only one option per group can be selected at a time.