Checkbox
Usage
Use checkboxes when people can pick any number of options (including none) — inspection items, vehicle features, which depots to include in a report — or to confirm a single statement. Use radios when only one answer is allowed, and a switch for a setting that applies immediately.
- Group related checkboxes in a fieldset with a legend that asks the question.
- Write labels as the thing being chosen ("Tachograph calibrated"), not "Yes".
- Vertical by default; horizontal only for 2–3 short options.
- Indeterminate is only for a parent "select all" whose children are partly selected.
Anatomy
- Box —
input[type=checkbox].checkbox__input(native,appearance: none), 24px - Check / dash mark — masked
::before - Label —
label.checkbox__label[for], part of the hit area - Hint (optional) —
.checkbox__hint, wired witharia-describedby - Group —
fieldset.checkbox-groupwith legend, hint, error and.checkbox-group__items
Examples
Hover and focus-visible are frozen with .is-hover and .is-focus-visible, which share their rules with the real pseudo-classes.
Checkbox
Available after the vehicle is on the rolling road.
Error: Confirm the vehicle is safe before closing the work order.
<div class="checkbox">
<input class="checkbox__input" type="checkbox" id="tyres" name="checks" value="tyres" aria-describedby="tyres-hint">
<label class="checkbox__label" for="tyres">Tyres checked for wear and pressure</label>
<p class="checkbox__hint" id="tyres-hint">Minimum tread depth 1.6 mm.</p>
</div>
<!-- Invalid single checkbox -->
<input class="checkbox__input" type="checkbox" id="safe" required aria-invalid="true" aria-describedby="safe-error">
<!-- Select all: js/checkbox.js keeps checked / indeterminate in sync -->
<input class="checkbox__input" type="checkbox" id="all" data-select-all aria-controls="v1 v2 v3">
Checkbox group
<fieldset class="fieldset checkbox-group [checkbox-group--horizontal]" aria-describedby="depots-hint depots-error">
<legend class="fieldset__legend">Which depots should the report include?</legend>
<p class="field__hint" id="depots-hint">Select all that apply.</p>
<p class="field__error" id="depots-error">…<span class="sr-only">Error: </span>Select at least one depot.</p>
<div class="checkbox-group__items">
<div class="checkbox">…North Yard…</div>
<div class="checkbox">…Harbour Road…</div>
</div>
</fieldset>
API
| Hook | Values | Purpose |
|---|---|---|
.checkbox, .checkbox__input, .checkbox__label, .checkbox__hint | block / parts | One checkbox |
.checkbox--sm | modifier class | 20px box for dense tables |
.checkbox-group (+ .fieldset), .checkbox-group__items | block / part | Group |
.checkbox-group--horizontal | modifier class | Wrapping row of short options |
checked, disabled, required | attribute | Native states |
aria-invalid="true", :user-invalid | attribute / pseudo-class | Single checkbox error |
.field__error inside the group | part | Group error (left rule + red boxes) |
data-indeterminate, data-select-all + aria-controls | attribute (js/checkbox.js) | Indeterminate and select-all |
.is-hover | .is-focus-visible | docs-only class | Freezes a state |
Do and don't
Accessibility
| Key | Behavior |
|---|---|
| Tab | Moves to the next checkbox (each is a tab stop) |
| Space | Toggles the focused checkbox |
- Role: native
checkbox; the indeterminate state is announced as "mixed" / "half checked". - Name from
<label for>; clicking the label toggles, so the hit area is the whole text (box is 24px). - Group:
fieldset+legendgives the question; hint and error are linked to the fieldset witharia-describedby. - Checked uses a check mark on a filled box, indeterminate a dash — shape plus color. Boxes have a 2px border at 3:1.
- Forced colors: the box uses
CanvasText/Highlightand the mark stays visible.
Tokens
| Custom property | Purpose |
|---|---|
--input-border, --input-bg | Unchecked box |
--color-action-primary-bg | -hover, --color-action-primary-fg | Checked box and mark |
--color-border-invalid | Invalid box, group error rule |
--color-bg-muted, --color-text-disabled | Disabled |
--icon-size-lg | -md, --radius-sm, --border-width-thick | Box size and shape |
--focus-ring-* | Focus |