Forms & Input
Radio Group
AvailableSelects one option from many. A prime example of arrow key navigation with roving tabindex.
What Is a Radio Group?
A radio button is a UI control that lets you choose exactly one option from a set. It's used for things like payment methods, sizes, and shipping options — any time you need to pick one and only one. A set of these buttons is called a radio group.
The difference from checkboxes: checkboxes allow multiple selections, while radios allow only one. The key challenge is conveying both this "only one" rule and the group's label to users who can't see the screen.
Why Does Accessibility Matter?
- Keyboard-only users. Native radio buttons let you Tab into the group, then use ↑↓←→ to move between options while simultaneously selecting them. A
<div>-based implementation won't respond to arrow keys, making it inoperable. - Screen reader users. A properly built radio group announces something like "Payment Method, Credit Card, radio button, selected, 1 of 3" — conveying the group name, role, selection state, and position. With
<div>elements, there's no indication that these items form a group of choices at all.
The fastest path is to wrap native radio inputs with the same name in a <fieldset> +<legend>.
Live Demo (Recommended Implementation)
A radio group for choosing a payment method. Without using a mouse, try pressing Tab to enter the group, then use the arrow keys.
Try it: Tab into the group → ↑ ↓ ← → to move between options (moving = selecting). Tab again to leave the group.
Tip
In a radio group, Tab stops only once for the entire group(not on each individual option). Navigation within the group is handled by arrow keys. This is the "roving tabindex" keyboard pattern, and native radios implement it automatically.
Keyboard Interaction
| Key | Action | Priority |
|---|---|---|
| Tab | Enter / leave the group (focus lands on the selected item) | Required |
| ↓ / → | Move to the next option and select it | Required |
| ↑ / ← | Move to the previous option and select it | Required |
| Space | Select the currently focused option | Required |
Note
All of these interactions come automatically when you use<input type="radio"> elements grouped under the same name. You don't need to write any arrow key handling yourself.
Required WAI-ARIA Roles & Attributes
With native elements, almost no ARIA attributes are needed.
| Target | Attribute / Role | Meaning |
|---|---|---|
| Each option | <input type="radio"> + same name | Automatically provides the radio role, single-selection behavior, and arrow key navigation. |
| Label | <label> | The accessible name for each option. Clicking the label also selects the option. |
| Group | <fieldset> + <legend> | Groups the options together and provides the group name (e.g., the question text). |
Note
If you absolutely must build a custom implementation, wrap items in role="radiogroup", give each item role="radio" + aria-checked, and implement roving tabindex (only the selected item gets tabindex="0", all others get tabindex="-1") along with manual arrow key handling. Using native elements makes all of this unnecessary.
Implementation: Recommended Pattern (Good)
Good / Recommended
Simply wrap native radio inputs with the same name in a <fieldset> + <legend>.
Markup:
<fieldset>
<legend>Payment Method</legend>
<!-- Grouped by the same name. Arrow key navigation & selection work natively -->
<label>
<input type="radio" name="pay" value="card" checked> Credit Card
</label>
<label>
<input type="radio" name="pay" value="bank"> Bank Transfer
</label>
<label>
<input type="radio" name="pay" value="cod"> Cash on Delivery
</label>
</fieldset>Script:
// No JS required.
// Grouping radios under the same name gives you "select only one",
// "arrow key navigation & selection", and "Tab into the group"
// — all as built-in browser behavior.Anti-pattern (Bad)
Below is a "radio-like" UI built with <div> elements.You can select options by clicking with a mouse, but arrow keys don't work and Tab won't even stop here.Neither the group name nor the "select only one" semantics are conveyed to assistive technologies.
Try it: Tab doesn't focus any option, arrow keys don't switch selection. Screen readers won't recognize this as a group of choices.
<!-- ❌ Anti-pattern: "radio-like" UI built with divs -->
<div class="radio-list">
<!-- No role, no name, arrow keys don't work. No group label either -->
<div class="radio" onclick="select(this)">Credit Card</div>
<div class="radio" onclick="select(this)">Bank Transfer</div>
<div class="radio" onclick="select(this)">Cash on Delivery</div>
</div>Bad / Avoid
Problems with this implementation:
- Not keyboard accessible —
divelements can't receive focus and don't respond to arrow keys. - No group semantics — neither
role="radiogroup"nor<fieldset>is present. - "Select only one" is not conveyed — without
role="radio"/aria-checked, the state and position are never announced. - Using checkboxes as a substitute for radios is also wrong (they allow multiple selections, reversing the intended semantics).
Implementation Checklist
- Each option is an <input type="radio"> element
- All radios in the group share the same name attribute
- Each radio is associated with a <label> element (wrapping or for/id)
- The group has a <fieldset> + <legend> to provide the group name
- Tab enters the group; arrow keys move between and select options
- Focus is visible (focus ring is not suppressed)
- For custom implementations only: role="radiogroup" / role="radio" / aria-checked and roving tabindex are implemented
Source (English):Radio Group Pattern — W3C APG(opens in a new tab)