Radio
A radio allows users to select exactly one option from a set.
Ready to use
Radio buttons allow users to select exactly one option from a list of at least two mutually exclusive choices. Selecting one option automatically deselects the previously selected one. The component is fully responsive and intentionally designed to be used across all viewports.
Anatomy
Section titled “Anatomy”- Control
- Selected indicator
- Label
When to use it
Section titled “When to use it”Use radio buttons when:
- The user must select exactly one option from a small list of mutually exclusive choices (typically 2–5).
- All available options should be visible at a glance for quick comparison.
- You want to provide a clear “recommended” or “current” state by pre-selecting a default.
Avoid radio buttons when:
- The user needs to select multiple items — use checkboxes.
- The list contains more than 5–6 options — use a dropdown to save space.
- The action is a binary on/off that takes effect immediately without a submit button — use a toggle switch.
Properties
Section titled “Properties”State
Default, Hover, Selected, Disabled, Disabled-Selected, and Focus. Selected fills the control; disabled mutes it but stays visible; focus shows a 2 px outline around the entire item.
Size
Two sizes — Small (typography-body-7) for dense forms, Large (typography-body-6) for primary selections or hero comparisons. Both keep the same control size; only the label typography changes.
Label
The visible label sits next to the control and is fully clickable, which keeps the touch target generous. Always associate the label with the input so screen-reader users hear the choice as they navigate.
Platform considerations
Section titled “Platform considerations”Desktop
Vertical stacking keeps the comparison readable. Keyboard arrow keys move focus logically between options inside the group.
Tablet
Same vertical stack. Touch and pointer both work because the entire label area is clickable.
Mobile
Stick with the vertical stack and pick the large size for primary choices so the touch target stays comfortable.
Best practices
Section titled “Best practices”Lean on native semantics so keyboard, focus, and assistive-tech behaviour come for free.
Do
Use radio buttons when the user must select exactly one option, wrap groups in a <fieldset> with a <legend>, pre-select a sensible default when one exists, associate a visible label with every radio, provide clear visual feedback for selected, unselected, and disabled states, and ensure arrow-key navigation moves focus logically between options.
Don't
Don’t reach for radio buttons when the user can select multiple options (use checkboxes), don’t reach for them when the list contains more than 5–6 options (use a dropdown), don’t reach for them for instant on/off actions (use a toggle), don’t recreate the control with <div> or <span> without ARIA roles, don’t rely on colour alone for the selected state, and don’t remove the browser focus outline unless you replace it with an accessible equivalent.
Content guidelines
Section titled “Content guidelines”Write each label so it stands on its own — users shouldn’t have to read the legend to understand a choice. Keep the wording parallel across the group (“Petrol”, “Hybrid”, “Electric” rather than “Petrol car”, “Hybrid”, “Fully electric vehicles”), use sentence case, and skip trailing punctuation. The group’s legend should pose a clear question or name the dimension the choices vary along.
Styles
Section titled “Styles”A radio allows users to select exactly one option from a set.
<label class="tng-radio-control"> <input type="radio" name="delivery" checked /> <span>Home delivery</span></label><label class="tng-radio-control"> <input type="radio" name="delivery" /> <span>Click and collect</span></label>Elements
Section titled “Elements”Grouping
Section titled “Grouping”Group related radios in a <fieldset> with a <legend> so assistive technology announces the group context.
<fieldset class="tng-stack"> <legend class="tng-text-title is-8 mb-xl"> Contact preference </legend> <label class="tng-radio-control"> <input type="radio" name="contact" checked /> <span>Email</span> </label> <label class="tng-radio-control"> <input type="radio" name="contact" /> <span>SMS</span> </label></fieldset><label class="tng-radio-control is-sm"> <input name="size" type="radio" /> <span>Small</span></label><label class="tng-radio-control is-lg"> <input name="size" type="radio" /> <span>Large</span></label>States
Section titled “States”Disabled
Section titled “Disabled”<label class="tng-radio-control"> <input type="radio" name="state" disabled /> <span>Disabled</span></label><label class="tng-radio-control"> <input type="radio" name="state" checked disabled /> <span>Selected and disabled</span></label>For designers
Section titled “For designers”- All states (default, hover, selected, disabled, focus) must maintain accessible contrast.
- Focus styles must remain visible and meet WCAG AA contrast requirements. Focus should be clearly distinguishable from hover.
- Colour tokens used should be semantic (e.g.
foreground/neutral/default) rather than fixed values. This ensures the component adapts correctly to different themes or surfaces. - The interactive area (radio button + label) must be large enough to support touch accessibility.
For developers
Section titled “For developers”To ensure the radio button meets WCAG 2.1 AA and supports assistive technologies, follow these implementation standards:
- Semantic HTML
- Use a native
<input type="radio">element. Do not recreate radio buttons using<div>or<span>. - The radio button must be associated with a
<label>using theforattribute or by wrapping the input inside the label. - Avoid adding click handlers to non-semantic elements to toggle the radio button.
- Wrap the set in a
<fieldset>and provide a label using<legend>. This ensures screen readers announce the category before the individual options.
- Use a native
- Keyboard Navigation
- The radio button group must be reachable using Tab navigation.
- Users must be able to move between options using Arrow keys.
- Do not override default keyboard behaviour unless providing a fully accessible alternative.
- Focus Ring / Visible Focus
- The radio button must display a visible focus style when focused via keyboard.
- The focus indicator must be clearly distinguishable and not rely only on colour.
- Never remove the browser default focus outline unless replacing it with an accessible equivalent.
- Focus styles must remain visible even when the radio button is hovered or checked.
- Screen Reader Support
- The radio button label must clearly describe the option or action it represents.
- Use
aria-describedbywhen additional helper text or error messages are present. - The checked and unchecked states must be correctly announced by assistive technologies.
- If the radio button is disabled, ensure the disabled state is conveyed programmatically.
- Interaction Feedback
- The selected state must be communicated via the native
checkedattribute. - Visual changes (filled circle, border) should reinforce state changes.
- Avoid relying solely on colour to indicate selected or unselected status.
- Error states must be clearly communicated visually and programmatically.
- The selected state must be communicated via the native
- Responsive and Tap Targets
- The interactive area must be at least 44 px in height to support touch accessibility.
- Ensure sufficient spacing between radio buttons when presented in a list to avoid accidental activation.
Semantic markup
Section titled “Semantic markup”Use native <input type="radio"> elements with a shared name value for each group. Wrap each input in a <label> to keep the full row clickable.
Keyboard interaction
Section titled “Keyboard interaction”- Tab moves focus to the selected radio in a group.
- Arrow keys move selection between options in the same group.
- Space selects the currently focused option.
- Focus visibility is handled by the
tng-focus-withinutility.
| Keys | Actions |
|---|---|
| Tab | Moves focus into and out of the radio button group |
| Arrow keys | Moves focus between radio button options |
| Space | Selects the focused radio button |
Group labels and descriptions
Section titled “Group labels and descriptions”Each radio group needs a visible label via <legend>. If helper or error text is present, connect it with aria-describedby.