What's new Report an issue
GIG Cymru NHS Wales, Digital Health and Care Wales

Radio

One choice from a short list, with every option visible at once. Past about seven options, use a Select instead.

Which one

ControlAnswersTakes effect
CheckboxAny number, including noneOn Save
RadioExactly one, all options visibleOn Save
SelectExactly one, from a longer listOn Save
SwitchOn or offImmediately

The group

Options sharing a name are what make one choice. That shared name is also why a radio group takes a single Tab stop, with the arrow keys moving between options.

Priority

How soon the patient should be seen.

<fieldset class="sr-radio-group">
  <legend class="sr-radio-group__legend">Priority</legend>
  <div class="sr-radio-group__options">
    <div class="sr-radio">
      <input class="sr-radio__input" type="radio" id="p1" name="pri" checked>
      <label class="sr-radio__label" for="p1">Routine</label>
    </div>
  </div>
</fieldset>

States

The ring is round and the checkbox is square. That shape difference is the only cue telling a reader one is single-select — so it is never restyled.

<!-- Rest, hover and focus come from the stylesheet. `name` is what binds
     the options into one choice, so it is present in every state. -->
<div class="sr-radio">
  <input class="sr-radio__input" type="radio" id="r1" name="s">
  <label class="sr-radio__label" for="r1">Unselected</label>
</div>

<div class="sr-radio">
  <input class="sr-radio__input" type="radio" id="r2" name="s" checked>
  <label class="sr-radio__label" for="r2">Selected</label>
</div>

<div class="sr-radio sr-radio--error">
  <input class="sr-radio__input" type="radio" id="r3" name="s">
  <label class="sr-radio__label" for="r3">Error</label>
</div>

<div class="sr-radio">
  <input class="sr-radio__input" type="radio" id="r4" name="s" disabled>
  <label class="sr-radio__label" for="r4">Disabled</label>
</div>

Type: Card Radio

A bordered box so each option can carry a description. Selection is the border turning navy, and the ring keeps its dot — so selection is never the border colour alone.

<div class="sr-radio sr-radio--card sr-radio--card-outline">
  <input class="sr-radio__input" type="radio" id="pw1" name="pathway">
  <label class="sr-radio__label" for="pw1">
    <span class="sr-radio__title">Two-week wait</span>
    <span class="sr-radio__description">Seen within 14 days of referral</span>
  </label>
</div>

Type: Card

The same box, with selection filling the whole card. Label, description and dot all invert together, so the card reads as one selected object rather than a box with a highlight.

<div class="sr-radio sr-radio--card sr-radio--card-filled">
  <input class="sr-radio__input" type="radio" id="cf1" name="pathway" checked>
  <label class="sr-radio__label" for="cf1">
    <span class="sr-radio__title">Two-week wait</span>
    <span class="sr-radio__description">Seen within 14 days of referral</span>
  </label>
</div>

Type: Card Icon

A 24px icon replaces the ring where the option has a recognisable mark. The icon is decorative — the label still carries the name, because an icon on its own does not identify a record type to someone who has not seen it before.

<!-- The icon renders AFTER the label in the DOM. An element between the
     input and the label breaks the `:checked +` adjacency the styling needs. -->
<div class="sr-radio sr-radio--card sr-radio--card-icon">
  <input class="sr-radio__input" type="radio" id="ci1" name="kind" checked>
  <label class="sr-radio__label" for="ci1">
    <span class="sr-radio__title">Diagnosis</span>
    <span class="sr-radio__description">Coded condition on the problem list</span>
  </label>
  <span class="sr-radio__icon" aria-hidden="true"><!-- Icon: clinical/result --></span>
</div>

Do not mix types within one group. A group of cards beside a group of simple radios is fine; a group that is half each is not.

Horizontal

Only for two or three short options. It wraps rather than overflows, and below 480px it should be vertical.

Sex

Error

One message for the whole group. Note there is no way back to "nothing selected" once an option is chosen — where "no answer" is meaningful, give it an option of its own.

Priority

Select a priority


A single choice from a short list, with every option visible at once.


When to use

When not to use

Types

TypeLeft of the labelSelection shown byUse for
Simple20px ringThe ring fillsThe default. Any ordinary form question
Card Radio20px ringThe card border turns navyOptions that each need a description
Card20px ringThe whole card fills navyThe same, where the choice is the main thing on the screen
Card Icon24px iconThe whole card fills navyOptions with a recognisable icon, a pathway, a record type

Do not mix types within one group. A group of cards next to a group of simple radios on the same screen is fine; a group that is half each is not.

How it works

Do & don't

DoDon't
Give every option a label that answers the legend's questionRely on the legend to complete a half-written label
Offer "Not known" explicitly when it is a real answerLeave the group unanswered as a way of meaning "not known"
Keep option order stable between visitsRe-order by recency, so the same answer moves
Use one type per groupMix card and simple options in one group
Let a long label wrapTruncate a label with an ellipsis

Accessibility

Known gaps

Accessibility requirements

RequirementWCAG SCHow Single Record meets itTest method
Group name is announced with each option1.3.1, 4.1.2A real fieldset and legend. hideLegend hides it visually only, so the name still reaches assistive technology.Screen reader announce
The group is one Tab stop2.1.1Native radio grouping by shared name: Tab enters the group, arrow keys move within it. No custom key handling, so this is exactly browser behaviour.Keyboard only
Selection is not colour alone1.4.1The ring fills and gains a white dot; a selected card inverts its whole surface as well as its border.Greyscale review
The card icon is not the label1.1.1The icon is aria-hidden and the visible label carries the name, so the option is identifiable without recognising the mark.Screen reader announce
Focus matches the target2.4.7A 3px Cyan/700 ring on the control for simple radios, and around the whole card for card types — because on a card the card is what is clicked.Keyboard tab
Error is exposed and actionable3.3.1, 3.3.3One message on the group, referenced from it, saying what to do ("Select a priority").Screen reader, submit empty
Required state is more than an asterisk3.3.2The asterisk is decorative; the group carries aria-required.Screen reader announce
Target size2.5.8The 20px ring relies on the spacing exception: 8px between options puts centres 28px apart. Card types are 56px tall and pass outright.Measure spacing
Text resizes to 200%1.4.4Labels wrap under themselves rather than under the ring, and cards size from their content.Browser zoom to 200%