Skip to main content

Checkbox

A small box that users can tick or untick to select or deselect an option. Use when users can pick more than one item from a list. Don't use when only one choice is allowed — use Radio Button instead.

OverviewStyleAccessibility

Description

A single checkbox is appropriate for a single binary decision: "I agree to the terms". A group of checkboxes is appropriate for multi-select lists. Standalone checkboxes should never need a fieldset.

Anatomy

PartRequired?Notes
Checkbox control Required The interactive square. Must be 16–20px for touch usability, with a minimum 44×44px hit area.
Checked indicator Conditional Checkmark shown when selected. A dash (—) indicates an indeterminate state in parent/child group patterns.
Label Required Plain language description of the option. Always visible — never use placeholder text as a label.
Group container Conditional A <fieldset> wrapping all related checkboxes. Required for groups; omit for standalone checkboxes.
Group label Conditional A <legend> describing what the group of checkboxes collectively represents. Required when using a fieldset.

States

State Behaviour
Unchecked Empty box. Default state.
Checked Box with checkmark. Option is selected.
Indeterminate Box with dash. Used in parent/child tree patterns when some — but not all — child items are checked. Not a user-selectable state; set via JavaScript.
Disabled Greyed out. Use only when a checkbox is unavailable for a specific, communicated reason. Disabled fields are not announced to screen readers — consider using a read-only alternative.
Focus Focus ring on control. 2px solid focus ring, --op-color-focus-ring, with 2px offset.
Error Red border + error message. Used when a required group has no selection. See Form Control documentation.

Usage guidelines

Checkbox vs Radio Button vs Switch

Control Use when
Checkbox Multiple selections are valid. "Which notification types do you want?"
Radio button Exactly one selection is required. "How often should this reminder fire?"
Switch A single setting is being toggled on or off with immediate effect.

Do / Don't

Do

Use positive language for checkbox labels. "Email me about new responses" is clearer than "Don't suppress email notifications".

Don't

Don't use a checkbox to trigger an immediate action. Checkboxes are form inputs — their effect applies on form submission, not on click. Use a Switch for immediate-effect toggles.

Do

Use <fieldset> + <legend> for all checkbox groups. This is what makes the group label accessible — CSS styling alone doesn't communicate group structure to screen readers.

Don't

Don't use checkboxes for a single required choice where exactly one option must be selected. That's a radio button.

Layout & Spacing

Element Spec
Control size 12 / 14 / 16 / 20 / 24px (XS to XL), medium 16px
Hit area 44×44px minimum (extend via padding)
Border radius --orbit-selection-control-radius
Gap (control to label) 4 / 8 / 8 / 10 / 12px by size
Gap (between items in group) --op-space-12
Label font size Same as the control size
Size Control Label Gap
Extra small 12px 12px 4px
Small 14px 14px 8px
Medium (default) 16px 16px 8px
Large 20px 20px 10px
Extra large 24px 24px 12px

The control is the same size as its label text. Values come from --orbit-selection-control-size-{xs|s|m|l|xl}-{control|font-size|gap}; a 44×44px hit area is still required around the smaller sizes.

Component tokens

Checkbox, radio and switch share the --orbit-selection-control-* tokens, so they are framework-neutral CSS variables that any framework (including React Aria components) can use without Web Awesome. Colours follow Light and Dark mode and the product theme, and every token aliases a Semantic token.

Token What it sets
--orbit-selection-control-background, -border Unchecked fill and outline. The border meets 3:1 against the surface.
--orbit-selection-control-checked-background, -checked-border, -checked-icon Checked fill, outline and the check mark or dot.
--orbit-selection-control-state-hover Translucent overlay for the hover state.
--orbit-selection-control-invalid-border, -invalid-message Outline and message colour when invalid.
--orbit-selection-control-disabled-background, -border, -checked-background, -checked-icon, -text Disabled colours.
--orbit-selection-control-label-color, -label-font-weight, -hint-color, -hint-font-size Label and hint text.
`--orbit-selection-control-focus-ring-{color width
--orbit-selection-control-radius, -border-width Corner radius and outline width.

States are Default, Hover, Invalid and Disabled. Focus is shown with the focus ring.

State Control background Border
Unchecked --op-color-bg-primary --op-color-border-strong
Checked --op-color-interactive-default --op-color-interactive-default
Indeterminate --op-color-interactive-default --op-color-interactive-default
Disabled --op-color-bg-disabled --op-color-border-default
Error --op-color-bg-primary --op-color-status-error

Keyboard interaction

KeyAction
Tab Moves focus to the checkbox (or the next checkbox in a group).
Space Toggles the checkbox state.

Why it matters

Checkbox groups are one of the most commonly mislabelled form patterns. When multiple checkboxes share a visual heading but aren't wrapped in a <fieldset>, a screen reader user hears each option in isolation — without knowing what question is being answered. The fieldset/legend combination is what connects the options to their group context.

Required ARIA and HTML

Pattern Requirement
Standalone checkbox Always use <label> wrapping the input and its visible text. Never use placeholder text as a label.
Checkbox group Wrap in <fieldset> with a <legend> that describes the group. Don't use a <div> with ARIA substitutes — the native elements are more reliable.
Required group The error message must be connected to the fieldset via aria-describedby. Don't rely on visual proximity alone.
Indeterminate The indeterminate property is JavaScript-only. It has no HTML attribute equivalent. Announce the state change programmatically if needed: aria-label="Select all (partially selected)".

Things to avoid

  • Don't style a <div> or <span> to look like a checkbox. Native <input type="checkbox"> provides keyboard, focus, and announcement behaviour for free.
  • Don't use custom checkboxes without role="checkbox", aria-checked, and full keyboard support if native inputs are unavailable.
  • Don't disable checkboxes that users might expect to interact with. If a checkbox is unavailable because of a condition, explain the condition nearby.

Was this page helpful?

Updated 2 October 2026