Checkbox
A checkbox lets people choose any number of options from a list, or confirm a single one, such as agreeing to terms. A dash marks a partial choice, which is how a parent checkbox shows that only some of its children are ticked. Watch the chameleon's checklist below: a box ticks, and a badge comes and goes.
Reference docs
Choosing a selection control
Four components capture a choice in a form. Each suits a different job:
- Checkbox: one or more options picked from a short list, or a single yes to confirm, such as "I agree to the terms".
- Switch: a setting that takes effect the moment it is flipped, such as Wi-Fi or dark mode.
- Radio buttons: exactly one option from a short list shown in full, such as delivery speed.
- Select: exactly one option from a longer list kept closed until opened, such as country.
Two jobs belong elsewhere. A choice made by clicking a compact tag, such as filtering results, is a filter chip, and a two-state setting in a toolbar is a toggle button.
Built in
- The default slot is the label, and a click on it toggles the box.
shows a partial selection with a dash.indeterminate- A badge needs no separate element:
sets its text,badge-value makes it a dot, andbadge-dot hides it until you clear it.badge-concealed ,name , andform-value make the checkbox take part in a form, including required validation and form reset.form-is-required- Its touch target is at least 48 by 48 pixels even when the box paints smaller (
).touch-target puts the label before or after the box, with no extra markup.label-position
Using checkboxes well
- In a list with sub-selections, set
on the parent yourself: checked when every child is, unchecked when none is, indeterminate when some are.indeterminate
These rules follow Material 3 Expressive's guidance for checkboxes, on material.io.
States
checkedindeterminateindeterminatechecked
Touch target
touch-targetoverflowoverflow spills an area of at least 48 by 48 pixels past the box, wrapper gives that area layout space, and none shrinks it to the box.
Badges
badge-valuebadge-dotbadge-concealedbadge-concealed
Forms
nameform-valueon when omitted. Two boxes can share a nameform-is-requiredchecked attribute.
Tick the terms and the state below follows; Start over returns the form to its authored state. The preview cannot submit a form, but a page that holds the same markup submits topics and terms as written, and refuses to submit while a required box is unticked.
Disabled
disabled<fieldset> disables the checkboxes it contains without setting disabled
Label position
label-positionleadingtrailingtrailing
Parent and children
A parent checkbox is checked when all its children are, unchecked when none are, and indeterminate when some are. The component does not work this out: the page sets checkedindeterminate
Properties
| Property | Attribute | Type | Description |
|---|---|---|---|
badgeConcealed | badge-concealed | booleandefault false | Hides the badge while keeping its value and dot setting, so clearing this property shows the same badge again. See Badges. |
badgeDot | badge-dot | booleandefault false | Shows the badge as a small dot with no text, whether or not badgeValue is set. See Badges. |
badgeValue | badge-value | string | The badge's text. While it is empty and badgeDot is not set, no badge renders. Ignored if badgeDot is set. See Badges. |
checked | checked | booleandefault false | Whether the checkbox is checked. A user's click updates it, and a form reset restores the state the checked attribute gave it. See States, Parent and children. |
disabled | disabled | boolean | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
formread-only | HTMLFormElement | The form the component belongs to, or null when it has none. | |
formIsRequired | form-is-required | booleandefault false | When true, require the checkbox to be checked when participating in form submission.See MDN: checkbox validation. See Forms. |
formValue | form-value | stringdefault on | The value submitted with a form while the checkbox is checked and not indeterminate.See MDN: checkbox value. See Forms. |
indeterminate | indeterminate | booleandefault false | Whether the checkbox shows the mixed state. A user's click clears it. While it is set, checked is not shown and the checkbox submits no value.See MDN: indeterminate state checkboxes. See States, Parent and children. |
labelPosition | label-positionleading, trailing | LabelPositionLabelPosition.Leading, .Trailingdefault LabelPosition.Trailing | Sets which side of the checkbox the label is on. See Label position. |
labelsread-only | NodeList | The <label> elements associated with the element. | |
name | name | string | The name the element's value is submitted under with its form. See Forms. |
touchTarget | touch-targetnone, overflow, wrapper | TouchTargetTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Touch target. |
validationMessageread-only | string | The message describing why the element is invalid, or an empty string when it is valid. | |
validityread-only | ValidityState | The element's ValidityState. | |
willValidateread-only | boolean | Whether the element takes part in constraint validation. False while it is disabled or read-only. |
Slots
| Slot | Description |
|---|---|
| (default) | The label content. |
Events
| Event | Type | Detail | Description |
|---|---|---|---|
change | Event | — | Fired after a user toggles the checkbox. Setting checked from code does not fire it. It bubbles. |
input | InputEvent | — | Fired as a user toggles the checkbox. Setting checked from code does not fire it. It bubbles and is composed. |
Methods
| Method | Returns | Description |
|---|---|---|
checkValidity() | boolean | Checks the element's validity and returns true if it is valid. If not, it dispatches an invalid event; nothing changes on screen. |
reportValidity() | boolean | Checks the element's validity and returns true if it is valid. If not, it dispatches a cancelable invalid event and, unless a listener cancels it, shows validationMessage as the field's error text and focuses the field. |
setCustomValidity(error: string) | void | Sets a custom validation message, which makes the element invalid. An empty string clears it. |
Props
| Prop | Type | Description |
|---|---|---|
badgeConcealed | booleandefault false | Hides the badge while keeping its value and dot setting, so clearing this property shows the same badge again. See Badges. |
badgeDot | booleandefault false | Shows the badge as a small dot with no text, whether or not badgeValue is set. See Badges. |
badgeValue | string | The badge's text. While it is empty and badgeDot is not set, no badge renders. Ignored if badgeDot is set. See Badges. |
checked | booleandefault false | Whether the checkbox is checked. A user's click updates it, and a form reset restores the state the checked attribute gave it. See States, Parent and children. |
disabled | boolean | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
formread-only (ref) | HTMLFormElement | The form the component belongs to, or null when it has none. |
formIsRequired | booleandefault false | When true, require the checkbox to be checked when participating in form submission.See MDN: checkbox validation. See Forms. |
formValue | stringdefault on | The value submitted with a form while the checkbox is checked and not indeterminate.See MDN: checkbox value. See Forms. |
indeterminate | booleandefault false | Whether the checkbox shows the mixed state. A user's click clears it. While it is set, checked is not shown and the checkbox submits no value.See MDN: indeterminate state checkboxes. See States, Parent and children. |
labelPosition | LabelPositionTypeLabelPosition.Leading, .Trailingdefault LabelPosition.Trailing | Sets which side of the checkbox the label is on. See Label position. |
labelsread-only (ref) | NodeList | The <label> elements associated with the element. |
name | string | The name the element's value is submitted under with its form. See Forms. |
touchTarget | TouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Touch target. |
validationMessageread-only (ref) | string | The message describing why the element is invalid, or an empty string when it is valid. |
validityread-only (ref) | ValidityState | The element's ValidityState. |
willValidateread-only (ref) | boolean | Whether the element takes part in constraint validation. False while it is disabled or read-only. |
Children
| Child | Description |
|---|---|
children | The label content. |
Events
| Prop | Argument | Description |
|---|---|---|
onChange | React.ChangeEvent<HTMLInputElement> | Fired after a user toggles the checkbox. Setting checked from code does not fire it. It bubbles. |
onInput | React.ChangeEvent<HTMLInputElement> | Fired as a user toggles the checkbox. Setting checked from code does not fire it. It bubbles and is composed. |
Methods
Call these on the element the ref holds.
| Method | Returns | Description |
|---|---|---|
checkValidity() | boolean | Checks the element's validity and returns true if it is valid. If not, it dispatches an invalid event; nothing changes on screen. |
reportValidity() | boolean | Checks the element's validity and returns true if it is valid. If not, it dispatches a cancelable invalid event and, unless a listener cancels it, shows validationMessage as the field's error text and focuses the field. |
setCustomValidity(error: string) | void | Sets a custom validation message, which makes the element invalid. An empty string clears it. |
Parameters
| Parameter | Type | Description |
|---|---|---|
BadgeConcealed | bool?default false | Hides the badge while keeping its value and dot setting, so clearing this property shows the same badge again. See Badges. |
BadgeDot | bool?default false | Shows the badge as a small dot with no text, whether or not BadgeValue is set. See Badges. |
BadgeValue | string? | The badge's text. While it is empty and BadgeDot is not set, no badge renders. Ignored if BadgeDot is set. See Badges. |
Disabled | bool? | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
FormIsRequired | bool?default false | When true, require the checkbox to be Checked when participating in form submission.See MDN: checkbox validation. See Forms. |
FormValue | string?default on | The value submitted with a form while the checkbox is checked and not indeterminate.See MDN: checkbox value. See Forms. |
Indeterminate | bool?default false | Whether the checkbox shows the mixed state. A user's click clears it. While it is set, Checked is not shown and the checkbox submits no value.See MDN: indeterminate state checkboxes. See States, Parent and children. |
LabelPosition | LabelPosition?LabelPosition.Leading, .Trailingdefault LabelPosition.Trailing | Sets which side of the checkbox the label is on. See Label position. |
Name | string? | The name the element's value is submitted under with its form. See Forms. |
TouchTarget | TouchTarget?TouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Touch target. |
Value | bool | — |
ValueExpression | Expression<Func<bool>>? | Gets or sets an expression that identifies the bound value. |
Render fragments
| Parameter | Type | Description |
|---|---|---|
ChildContent | RenderFragment? | The label content. |
Event callbacks
| Parameter | Type | Description |
|---|---|---|
OnChange | EventCallback<ChangeEventArgs> | Fired after a user toggles the checkbox. Setting Checked from code does not fire it. It bubbles. |
OnInput | EventCallback<ChangeEventArgs> | Fired as a user toggles the checkbox. Setting Checked from code does not fire it. It bubbles and is composed. |
Inputs
| Input | Type | Description |
|---|---|---|
badgeConcealed | booleandefault false | Hides the badge while keeping its value and dot setting, so clearing this property shows the same badge again. See Badges. |
badgeDot | booleandefault false | Shows the badge as a small dot with no text, whether or not badgeValue is set. See Badges. |
badgeValue | string | The badge's text. While it is empty and badgeDot is not set, no badge renders. Ignored if badgeDot is set. See Badges. |
checked | booleandefault false | Whether the checkbox is checked. A user's click updates it, and a form reset restores the state the checked attribute gave it. See States, Parent and children. |
disabled | boolean | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
formIsRequired | booleandefault false | When true, require the checkbox to be checked when participating in form submission.See MDN: checkbox validation. See Forms. |
formValue | stringdefault on | The value submitted with a form while the checkbox is checked and not indeterminate.See MDN: checkbox value. See Forms. |
indeterminate | booleandefault false | Whether the checkbox shows the mixed state. A user's click clears it. While it is set, checked is not shown and the checkbox submits no value.See MDN: indeterminate state checkboxes. See States, Parent and children. |
labelPosition | LabelPositionTypeLabelPosition.Leading, .Trailingdefault LabelPosition.Trailing | Sets which side of the checkbox the label is on. See Label position. |
name | string | The name the element's value is submitted under with its form. See Forms. |
touchTarget | TouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Touch target. |
value | boolean | — |
Content projection
| Content | Description |
|---|---|
content with no slot | The label content. |
Outputs
| Output | Event | Description |
|---|---|---|
cwChange | Event | Fired after a user toggles the checkbox. Setting checked from code does not fire it. It bubbles. |
cwInput | InputEvent | Fired as a user toggles the checkbox. Setting checked from code does not fire it. It bubbles and is composed. |
Props
| Prop | Type | Description |
|---|---|---|
badgeConcealed | booleandefault false | Hides the badge while keeping its value and dot setting, so clearing this property shows the same badge again. See Badges. |
badgeDot | booleandefault false | Shows the badge as a small dot with no text, whether or not badgeValue is set. See Badges. |
badgeValue | string | The badge's text. While it is empty and badgeDot is not set, no badge renders. Ignored if badgeDot is set. See Badges. |
checked | booleandefault false | Whether the checkbox is checked. A user's click updates it, and a form reset restores the state the checked attribute gave it. See States, Parent and children. |
disabled | boolean | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
formIsRequired | booleandefault false | When true, require the checkbox to be checked when participating in form submission.See MDN: checkbox validation. See Forms. |
formValue | stringdefault on | The value submitted with a form while the checkbox is checked and not indeterminate.See MDN: checkbox value. See Forms. |
indeterminate | booleandefault false | Whether the checkbox shows the mixed state. A user's click clears it. While it is set, checked is not shown and the checkbox submits no value.See MDN: indeterminate state checkboxes. See States, Parent and children. |
labelPosition | LabelPositionTypeLabelPosition.Leading, .Trailingdefault LabelPosition.Trailing | Sets which side of the checkbox the label is on. See Label position. |
name | string | The name the element's value is submitted under with its form. See Forms. |
touchTarget | TouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Touch target. |
Slots
| Slot | Description |
|---|---|
default | The label content. |
Events
| Event | Type | Description |
|---|---|---|
change | Event | Fired after a user toggles the checkbox. Setting checked from code does not fire it. It bubbles. |
input | InputEvent | Fired as a user toggles the checkbox. Setting checked from code does not fire it. It bubbles and is composed. |
Props
| Prop | Type | Description |
|---|---|---|
badgeConcealed | booleandefault false | Hides the badge while keeping its value and dot setting, so clearing this property shows the same badge again. See Badges. |
badgeDot | booleandefault false | Shows the badge as a small dot with no text, whether or not badgeValue is set. See Badges. |
badgeValue | string | The badge's text. While it is empty and badgeDot is not set, no badge renders. Ignored if badgeDot is set. See Badges. |
checked | booleandefault false | Whether the checkbox is checked. A user's click updates it, and a form reset restores the state the checked attribute gave it. See States, Parent and children. |
disabled | boolean | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
formIsRequired | booleandefault false | When true, require the checkbox to be checked when participating in form submission.See MDN: checkbox validation. See Forms. |
formValue | stringdefault on | The value submitted with a form while the checkbox is checked and not indeterminate.See MDN: checkbox value. See Forms. |
indeterminate | booleandefault false | Whether the checkbox shows the mixed state. A user's click clears it. While it is set, checked is not shown and the checkbox submits no value.See MDN: indeterminate state checkboxes. See States, Parent and children. |
labelPosition | LabelPositionTypeLabelPosition.Leading, .Trailingdefault LabelPosition.Trailing | Sets which side of the checkbox the label is on. See Label position. |
name | string | The name the element's value is submitted under with its form. See Forms. |
touchTarget | TouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Touch target. |
Snippets
| Snippet | Description |
|---|---|
children | The label content. |
Events
| Prop | Type | Description |
|---|---|---|
onChange | Event | Fired after a user toggles the checkbox. Setting checked from code does not fire it. It bubbles. |
onInput | InputEvent | Fired as a user toggles the checkbox. Setting checked from code does not fire it. It bubbles and is composed. |
A value is what the token defaults to; selecting it copies the token's name.
Tokens
| Token | Value |
|---|---|
--ct-checkbox-container-size | 18px --ct-checkbox-container-size |
--ct-checkbox-disabled-container-opacity | 0.38 --ct-checkbox-disabled-container-opacity |
--ct-checkbox-disabled-label-text-color | --ct-sys-color-on-surface --ct-checkbox-disabled-label-text-color |
--ct-checkbox-disabled-label-text-opacity | 0.38 --ct-checkbox-disabled-label-text-opacity |
--ct-checkbox-disabled-outline-color | --ct-sys-color-on-surface --ct-checkbox-disabled-outline-color |
--ct-checkbox-focus-outline-color | --ct-sys-color-on-surface --ct-checkbox-focus-outline-color |
--ct-checkbox-focus-outline-width | 2px --ct-checkbox-focus-outline-width |
--ct-checkbox-hover-outline-color | --ct-sys-color-on-surface --ct-checkbox-hover-outline-color |
--ct-checkbox-hover-outline-width | 2px --ct-checkbox-hover-outline-width |
--ct-checkbox-hover-state-layer-color | --ct-sys-color-on-surface --ct-checkbox-hover-state-layer-color |
--ct-checkbox-hover-state-layer-opacity | --ct-sys-state-hover-state-layer-opacity --ct-checkbox-hover-state-layer-opacity |
--ct-checkbox-icon-size | 18px --ct-checkbox-icon-size |
--ct-checkbox-label-gap | 18px --ct-checkbox-label-gap |
--ct-checkbox-label-text-color | --ct-sys-color-on-surface --ct-checkbox-label-text-color |
--ct-checkbox-label-text-font | --ct-sys-typescale-label-large-font --ct-checkbox-label-text-font |
--ct-checkbox-label-text-line-height | --ct-sys-typescale-label-large-line-height --ct-checkbox-label-text-line-height |
--ct-checkbox-label-text-size | --ct-sys-typescale-label-large-size --ct-checkbox-label-text-size |
--ct-checkbox-label-text-weight | --ct-sys-typescale-label-large-weight --ct-checkbox-label-text-weight |
--ct-checkbox-outline-color | --ct-sys-color-on-surface-variant --ct-checkbox-outline-color |
--ct-checkbox-outline-width | 2px --ct-checkbox-outline-width |
--ct-checkbox-pressed-outline-color | --ct-sys-color-on-surface --ct-checkbox-pressed-outline-color |
--ct-checkbox-pressed-outline-width | 2px --ct-checkbox-pressed-outline-width |
--ct-checkbox-pressed-state-layer-color | --ct-sys-color-primary --ct-checkbox-pressed-state-layer-color |
--ct-checkbox-pressed-state-layer-opacity | --ct-sys-state-pressed-state-layer-opacity --ct-checkbox-pressed-state-layer-opacity |
--ct-checkbox-selected-container-color | --ct-sys-color-primary --ct-checkbox-selected-container-color |
--ct-checkbox-selected-disabled-container-color | --ct-sys-color-on-surface --ct-checkbox-selected-disabled-container-color |
--ct-checkbox-selected-disabled-container-opacity | 0.38 --ct-checkbox-selected-disabled-container-opacity |
--ct-checkbox-selected-disabled-icon-color | --ct-sys-color-surface --ct-checkbox-selected-disabled-icon-color |
--ct-checkbox-selected-focus-icon-color | --ct-sys-color-on-primary --ct-checkbox-selected-focus-icon-color |
--ct-checkbox-selected-hover-icon-color | --ct-sys-color-on-primary --ct-checkbox-selected-hover-icon-color |
--ct-checkbox-selected-hover-state-layer-color | --ct-sys-color-primary --ct-checkbox-selected-hover-state-layer-color |
--ct-checkbox-selected-hover-state-layer-opacity | --ct-sys-state-hover-state-layer-opacity --ct-checkbox-selected-hover-state-layer-opacity |
--ct-checkbox-selected-icon-color | --ct-sys-color-on-primary --ct-checkbox-selected-icon-color |
--ct-checkbox-selected-pressed-icon-color | --ct-sys-color-on-primary --ct-checkbox-selected-pressed-icon-color |
--ct-checkbox-selected-pressed-state-layer-color | --ct-sys-color-on-surface --ct-checkbox-selected-pressed-state-layer-color |
--ct-checkbox-selected-pressed-state-layer-opacity | --ct-sys-state-pressed-state-layer-opacity --ct-checkbox-selected-pressed-state-layer-opacity |
--ct-checkbox-state-layer-radius | --ct-sys-corner-radius-full --ct-checkbox-state-layer-radius |
--ct-checkbox-state-layer-size | 40px --ct-checkbox-state-layer-size |
Names and states
A checkbox follows the WAI-ARIA Authoring Practices: Checkbox pattern. It is one focus stop.
- The accessible name comes from the default slot, which labels the checkbox, or from
aria-label. - Give a checkbox with no visible label an
aria-label, and leave it empty, whitespace included. aria-labelandaria-invalidare the only ARIA attributes a checkbox honors. Any otheraria-*you set on it has no effect.aria-invalidis announced, but nothing draws an error state, so show your own error text beside the checkbox. is announced as mixed.indeterminate- A badge is not part of the accessible name. A dot or concealed badge is hidden from assistive technology, so put any count that matters in the label.
- A checkbox has no built-in tooltip. A standalone plain or rich tooltip anchored on it describes the checkbox, so a screen reader reads that tooltip's text after the name.
- A setting that applies the moment it changes suits a switch, and exactly one choice from a short list suits radio buttons.
Keyboard and focus
| Key | Action |
|---|---|
| Tab | Moves focus to the checkbox, or past it |
| Shift+Tab | Moves focus to the previous control |
| Space | Toggles the checkbox |
Space toggles and Tab moves on, as for a native checkbox; Enter does not toggle a checkbox.
- A focus ring shows on keyboard focus only.
removes the checkbox from the Tab order and stops activation. A disableddisabled<fieldset>has the same effect on the checkboxes it contains.
Pointer and touch
The touch target is at least 48 by 48 pixels, so with the default it exceeds the 24 by 24 pixels WCAG 2.5.8 asks for while the box paints smaller. Setting touch-targetnone
Display settings
- Forced colors: the box outline is
CanvasText(GrayTextwhen disabled), and a checked fill isButtonTextwith aCanvasmark. A disabled checked box drops the fill and draws aGrayTextmark. Transitions stop, and hover draws a two-pixelButtonTextring around the box and press a four-pixel one. - Reduced motion: the mark and fill transitions take no time, and the press ripple is skipped.
Standards
With its defaults, the checkbox meets three WCAG 2.2 success criteria:
Three more depend on how you use it: