Loading Developer Playground

Loading ...

Skip to main content
ARIA ROLEComposite RolesMutually exclusiveForm controlArrow navigation

radiogroup

Groups two or more radio buttons so only one can be selected at a time. Provides an accessible label and keyboard behavior for the entire set.

Live Example

Notification Radiogroup

Custom-styled radios grouped with semantic fieldset/legend and keyboard support.

Notification preference

Purpose

Let people pick a single option out of a short, related set.

Structure

Contains role="radio" children—never mix with checkboxes.

Screen Reader

Announces “radio group” with position (2 of 4, etc.).

When to Use

1

Decision questions

Choose plan tiers, shipping methods, yes/no responses.

2

Settings toggles

Switch between modes (light/dark), notifications frequency, etc.

3

Step forms

Collect mutually exclusive answers in onboarding or multi-step flows.

Required Structure

Accessible name

aria-labelledby or aria-label must describe the entire group, not individual radios.

Radio focus

Only one radio should be in the tab order at a time. Use roving tabindex to keep focus tight.

Help + errors

Associate helper/error text via aria-describedby for validation guidance.

Keyboard Interaction Model

ActionKeysResult
Move selectionArrowLeft / ArrowRight / ArrowUp / ArrowDownMoves focus and selection to adjacent radio.
Select optionSpaceActivates the focused radio button.
TabTab / Shift+TabMoves out of the radiogroup once a radio has focus.

Required States & Properties

aria-labelledbyRequired

Reference a heading or label element to title the group.

aria-describedbyOptional

Point to helper or error copy that applies to the whole group.

aria-requiredOptional

Mark the group required when at least one radio must be selected.

aria-invalidOptional

Set true when validation fails. Pair with descriptive error text.

Implementation Checklist

  • Ensure only one radio has tabindex="0". Others should use -1 and rely on arrow keys for focus.

  • Wrap each radio label in a <label> to increase the tap target and automatically link inputs.

  • Keep DOM order consistent with visual order to avoid confusing keyboard users.

  • Announce dynamic changes (e.g., price updates) via aria-live when selection triggers new content.

Code Examples

Radiogroup with Legend

Fieldset + legend automatically label the radios.

<fieldset role="radiogroup" aria-labelledby="plan-label">
  <legend id="plan-label">Select a billing plan</legend>
  <label>
    <input type="radio" name="plan" value="starter" checked />
    Starter — $19/mo
  </label>
  <label>
    <input type="radio" name="plan" value="growth" />
    Growth — $49/mo
  </label>
  <label>
    <input type="radio" name="plan" value="scale" />
    Scale — $99/mo
  </label>
</fieldset>

Custom Radios with Buttons

Div-based radios require role and aria-checked.

<div role="radiogroup" aria-label="Delivery speed">
  <div role="radio" aria-checked="true" tabindex="0">Standard (3–5 days)</div>
  <div role="radio" aria-checked="false" tabindex="-1">Express (2-day)</div>
  <div role="radio" aria-checked="false" tabindex="-1">Overnight</div>
</div>

Best Practices

🧭

Keep choices short

Use concise labels so screen readers can quickly parse all options.

ℹ️

Explain impact

Add helper text describing what changes when an option is selected.

Confirm visually

Use strong focus + selected indicators for sighted users.

Common Mistakes

Treating radios as checkboxes

Allowing multiple radios to be selected simultaneously

Ensure changing one radio automatically unchecks the rest.

No group label

Screen readers announce “radio button” with no context.

Add aria-labelledby or wrap in a fieldset + legend.

Related Roles & Patterns

radio

Child role that represents each option.

Learn more

group

Generic grouping role when fieldset is impractical.

Learn more

form

Contains entire forms that may include radiogroups.

Learn more