Components · Inputs
Checkbox
Independent on/off choices. Several checkboxes in a group are several separate yes/no questions — which is what separates them from radio buttons.
Figma source: Checkbox ↗Examples
<fieldset class="cds-choice-group">
<legend class="cds-field__label">Compliance review required</legend>
<label class="cds-choice">
<input class="cds-choice__control" type="checkbox" checked> Human subjects (IRB)
</label>
<label class="cds-choice">
<input class="cds-choice__control" type="checkbox"> Animal subjects (IACUC)
</label>
</fieldset>The checkboxes above are live — click the label text as well as the box, since the whole label is the target.
Figma properties
| Property | Values | Notes |
|---|---|---|
Checked | Checked · Unchecked | Selection state. |
State | Default · Disabled · Focused · Error | Runtime state. |
Checkbox Text | text | The label. |
The variant set has Checked and Unchecked only. Any “select all” checkbox above a list — which the Table component’s header row has — needs a third, indeterminate state for when some but not all rows are selected. Without it, a partially-selected list shows an unchecked box, and clicking it appears to do nothing.
In HTML this is el.indeterminate = true (a property, not an attribute)
plus aria-checked="mixed". Worth adding to the Figma set.
Usage
When to use it
- Use for independent yes/no choices, where each box is its own question.
- Use a single checkbox for a lone opt-in — “Email me when the status changes”.
- Wrap a group in
<fieldset>with a<legend>naming the question. - Write labels as positive statements, so checking means yes.
When not to use it
Accessibility
- Wrap the input in its
<label>, or bind withfor/id. The whole label must be clickable — a 16px box alone is a poor target. - Group related boxes in
<fieldset>+<legend>so the group’s question is announced with each option. - Never take checkboxes out of the tab order. Each is individually focusable — unlike radios, which share one tab stop.
- For “select all”, set the
indeterminateproperty andaria-checked="mixed".
Tokens consumed
| Token | Applied to | Resolves to |
|---|---|---|
--primary-brand-color | Checked fill (via accent-color) | #0076b6 |
--error-border | Error outline | --color-red-500 |
--disabled-text | Disabled label | #888c8c |
--spacing-8 | Gap between box and label | 8px — the label rule from the grid |