Skip to the page

MCSS-Lite 0.4.1

GitHub

Radio c-radio

BetaComponent · since 0.4.0

A native radio button with its label: pick exactly one option from a short, visible list.

Pick this part

Pick c-radio for

  • Exactly one choice from 2 to 6 options that people should compare side by side.
  • A choice where seeing every option helps the decision, such as a delivery speed or a plan.

Pick another part for

  • Any number of options may be chosen: use c-checkbox.
  • An on/off setting that applies immediately: use c-toggle.
  • More than about 7 options: use a c-input on a <select>.

Build it

  1. Start with <div> and add class="c-radio".
  2. Add the required parts: c-radio__input, c-radio__label.
  3. Add the parts you need: c-radio__hint.
  4. Set state on the native control, never with data-state: :checked, :disabled.
Delivery speed

3 to 5 working days, free.

Order by 4pm, £4.99.

Show markup 19 lines
<fieldset class="c-form-field">
  <legend class="c-form-field__label">Delivery speed</legend>
  <div class="l-stack l-stack--sm">
    <div class="c-radio">
      <input class="c-radio__input" type="radio" id="delivery-standard" name="delivery" value="standard" checked aria-describedby="delivery-standard-hint">
      <label class="c-radio__label" for="delivery-standard">Standard</label>
      <p class="c-radio__hint" id="delivery-standard-hint">3 to 5 working days, free.</p>
    </div>
    <div class="c-radio">
      <input class="c-radio__input" type="radio" id="delivery-next" name="delivery" value="next-day" aria-describedby="delivery-next-hint">
      <label class="c-radio__label" for="delivery-next">Next day</label>
      <p class="c-radio__hint" id="delivery-next-hint">Order by 4pm, £4.99.</p>
    </div>
    <div class="c-radio">
      <input class="c-radio__input" type="radio" id="delivery-same" name="delivery" value="same-day" disabled>
      <label class="c-radio__label" for="delivery-same">Same day (not available in your area)</label>
    </div>
  </div>
</fieldset>

Check your build

Each piece that doesn't fit was run through mcss-lite validate when this page was built. The output below is real.

Fits

Put the group in a fieldset with a legend, and give every radio the same name.

Delivery speed

3 to 5 working days, free.

Show markup 14 lines
<fieldset class="c-form-field">
  <legend class="c-form-field__label">Delivery speed</legend>
  <div class="l-stack l-stack--sm">
    <div class="c-radio">
      <input class="c-radio__input" type="radio" id="speed-standard" name="speed" value="standard" checked aria-describedby="speed-standard-hint">
      <label class="c-radio__label" for="speed-standard">Standard</label>
      <p class="c-radio__hint" id="speed-standard-hint">3 to 5 working days, free.</p>
    </div>
    <div class="c-radio">
      <input class="c-radio__input" type="radio" id="speed-next" name="speed" value="next-day">
      <label class="c-radio__label" for="speed-next">Next day</label>
    </div>
  </div>
</fieldset>

validate: 0 issues

Doesn't fit

Don't mark a group error with aria-invalid on each radio; ARIA doesn't allow it there. Put the error on the fieldset.

<fieldset class="c-form-field" data-state="error">
  <legend class="c-form-field__label">Delivery speed</legend>
  <div class="c-radio">
    <input class="c-radio__input" type="radio" id="speed-x" name="speed-x" value="standard">
    <label class="c-radio__label" for="speed-x">Standard</label>
  </div>
</fieldset>

validate

  • warning data-state="error" on a <fieldset> also needs aria-describedby pointing at the c-form-field__error message. [state-pair]

Spec sheet

Apply to <div>

Elements
ClassOnWhat it does
c-radio__input required<input>The native control. Carries every state: checked, disabled.
c-radio__label required<label>The visible label, linked with for/id. Clicking it toggles the control and pads the hit area.
c-radio__hint<p> <div> <span>Optional one-line hint under the label, linked with aria-describedby.
States
StateMeaningPair it with
:checkedSelected: an ink stud seated in the ring.Use the checked attribute, never data-state.
:disabledCannot be chosen. Dashed ring, ghosted label.Use the disabled attribute, and say nearby why it is unavailable.
Show tokens 4
Tokens
TokenValue (light / dark)
--checkbox-size1.5rem
--checkbox-background#ffffff / #14294d
--checkbox-border#1a1d20 / #a9bacb
--radio-dot#1a1d20 / #e6edf4

Accessibility

  • Keep native <input type="radio"> elements sharing one name: the browser handles arrow keys and single selection.
  • Wrap the group in fieldset + legend so the question is read with every option.
  • Link hints with aria-describedby on the input.
Keyboard
KeyWhat it does
TabMoves focus into the group, to the checked radio (or the first), and out again.
Arrow keysMove to and select the next or previous radio.
SpaceSelects the focused radio if nothing is selected.

Wording

  1. The legend asks the question; each label is a short answer in sentence case.
  2. Use a hint for the detail that decides the choice: price, time, consequence.

All content rules

Fits with

Researched from