Skip to content

Checkbox

A tick box built on the native <input type="checkbox">, rendered as <input is="root-checkbox">.

Usage

<input is="root-checkbox" type="checkbox" data-label="Accept terms" />

The field composition is the shared one (fieldDecorator): a [field-wrapper] span draws the box, the native input stays in the DOM as [sr-only] - still the focus target and still what assistive tech reads - and data-label, data-hint, required and data-invalid behave as they do on Input.

<label>
  <span data-part="label">Accept terms</span>
  <span field-wrapper>
    <input is="root-checkbox" type="checkbox" sr-only />
  </span>
</label>

States

Unchecked is the page ground with a Neutral 400 border; checked fills with Default 400 and puts the tick on it in the pole that reads against it. Hover and :active walk one and two ramp steps deeper - on the border when unchecked, on the fill when checked - and the whole label is the target, so pointing at the text moves the box.

<input is="root-checkbox" type="checkbox" data-label="Unchecked" />
<input is="root-checkbox" type="checkbox" data-label="Checked" checked />
<input is="root-checkbox" type="checkbox" data-label="Indeterminate" indeterminate />
<input is="root-checkbox" type="checkbox" data-label="Focused" data-demo="focus" />
<input is="root-checkbox" type="checkbox" data-label="Focused, checked" checked data-demo="focus" />

The last two wear the focus ring without being focused: data-demo="focus" is the docs' own marker, and Focus says what it draws.

disabled steps out of both ramps onto Neutral 200, with the mark at Neutral 400: a disabled tick is still readable, just not addressed to anyone.

<input is="root-checkbox" type="checkbox" data-label="Disabled" disabled />
<input is="root-checkbox" type="checkbox" data-label="Disabled, checked" checked disabled />
<input is="root-checkbox" type="checkbox" data-label="Disabled, indeterminate" indeterminate disabled />

Indeterminate

The indeterminate attribute reflects onto the native .indeterminate property - which announces as aria-checked="mixed" - and draws a centred bar instead of the tick. It takes precedence over checked, which is the native convention: a group that is partly checked reads as partly checked. A user toggle resolves the mixed state, clearing it automatically.

The case it is for is a parent of a group:

<input is="root-checkbox" type="checkbox" data-label="Select all" indeterminate />
<input is="root-checkbox" type="checkbox" data-label="Comments" checked />
<input is="root-checkbox" type="checkbox" data-label="Mentions" />

Sizes

data-size takes small, medium and large; medium is the default and needs no value written. The box measures 24 / 20 / 16px on the fields' radius steps, the tick is the box less two, and small drops to a 1px border - at 16px a 2px one eats the box. The label follows: the md type step at large and medium, sm at small.

<input is="root-checkbox" type="checkbox" data-size="large" data-label="Large" checked />
<input is="root-checkbox" type="checkbox" data-label="Medium" checked />
<input is="root-checkbox" type="checkbox" data-size="small" data-label="Small" checked />

Description

data-hint puts a description under the label, indented past the box so it sits under the text and reads as this control's rather than the next one's.

<input
  is="root-checkbox"
  type="checkbox"
  data-label="Email me about releases"
  data-hint="No more than one message a month, and you can turn it off from here."
/>

required draws the asterisk beside the label, and data-invalid sets aria-invalid on the control.

<input is="root-checkbox" type="checkbox" required data-label="Accept terms" data-invalid="true" data-error="Required to continue" />

Label placement

The label sits after the box by default. data-label-position moves it to any of the four sides - inline-start, block-start, inline-end (the default), block-end - logically, so the sides follow the writing mode.

All four below, clockwise from the top, stacked in a <fieldset>: the group is the component's own (see above), and it lays its rows out in a column - which is what lets the two block placements be read as above and below rather than as two columns that happen to be taller than the rest of the row.

<fieldset>
  <input is="root-checkbox" type="checkbox" data-label="Above the box" data-label-position="block-start" />
  <input is="root-checkbox" type="checkbox" data-label="After the box" data-label-position="inline-end" />
  <input is="root-checkbox" type="checkbox" data-label="Below the box" data-label-position="block-end" />
  <input is="root-checkbox" type="checkbox" data-label="Before the box" data-label-position="inline-start" />
</fieldset>

Focus

The ring is the foundations', drawn around the wrapper: the input is [sr-only] but never hidden, so it is what takes focus and _focus.css is what draws it. The component declares no outline-* of its own.

<input is="root-checkbox" type="checkbox" data-label="Tab to me" />

Focus only exists while something has it, so the example above shows nothing until you reach it. data-demo="focus" is the docs' own marker - not a component attribute - and it draws the same ring, from the same tokens, on the same element the real one lands on:

<input is="root-checkbox" type="checkbox" data-label="Focused" data-demo="focus" />
<input is="root-checkbox" type="checkbox" data-label="Focused, checked" checked data-demo="focus" />

Attributes

Attribute Type Default Description
type 'checkbox' 'checkbox' Input type
checked boolean false Checked state
indeterminate boolean false Mixed state (bar + aria-checked="mixed"); cleared on toggle
disabled boolean false Disables the input
data-size 'small' | 'medium' | 'large' 'medium' Box, tick, border and type step
data-label string - Label text; the component builds the <label>
data-hint string - Description under the label
required boolean false Marks the field required and draws the asterisk
data-label-position 'inline-start' | 'block-start' | 'inline-end' | 'block-end' 'inline-end' Which side the label text sits on
data-invalid 'true' - Marks the control invalid: sets aria-invalid
data-error string - Message shown in place of the description while invalid

Events

Event Detail Description
root-checkbox.input { value } Fired on input
root-checkbox.change { value } Fired on change
root-checkbox.focus { value } Fired on focus
root-checkbox.blur { value } Fired on blur
root-checkbox.invalid { value } Fired on validation failure
root-checkbox.data-label.change { value, oldValue } Fired when the label text changes

Extends

HTMLInputElement - use with <input is="root-checkbox">.