Skip to main content

Theme config

Theme mode

Color palette

Grays

Border radii/radiuses/radiopedes/you know
Border radius
Field border radius
Button border radius
All
Components
Guides
API
Recent

    Components

    Checkbox

    See also: Checkbox field group.

    Full supportSupported since v105.Full supportSupported since v121.Full supportSupported since v15.4.

    Anatomy

    • label.ui-checkbox

      Container element.

    • <input>

      The checkbox input.

    • .ui-label

      The label.

    • .ui-end-text

      Supporting text displayed below the label.

    <!-- Checked -->
    <label class="ui-checkbox">
    <input name="checkbox-variants" type="checkbox" checked />
    <span class="ui-sr-only">Checked</span>
    </label>
    <!-- Unchecked -->
    <label class="ui-checkbox">
    <input name="checkbox-variants" type="checkbox" />
    <span class="ui-sr-only">Unchecked</span>
    </label>
    <!-- Indeterminate -->
    <label class="ui-checkbox">
    <input name="checkbox-variants" type="checkbox" data-indeterminate />
    <span class="ui-sr-only">Indeterminate</span>
    </label>
    <!-- Disabled -->
    <label class="ui-checkbox">
    <input name="checkbox-variants" type="checkbox" disabled />
    <span class="ui-sr-only">Disabled</span>
    </label>
    <!-- Checked and disabled -->
    <label class="ui-checkbox">
    <input name="checkbox-variants" type="checkbox" checked disabled />
    <span class="ui-sr-only">Checked and disabled</span>
    </label>

    Visible label

    Render the label text inside an element with a .ui-label class. Also, don't miss the info on label accessibility.

    <label class="ui-checkbox">
    <input name="checkbox-visible-label" type="checkbox" checked />
    <span class="ui-label">Choice A</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-visible-label" type="checkbox" disabled />
    <span class="ui-label">Disabled</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-visible-label" type="checkbox" checked disabled />
    <span class="ui-label">Checked and disabled</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-visible-label" type="checkbox" />
    <span class="ui-label">
    Long text dolor amet mustache knausgaard +1, blue bottle waistcoat tbh
    semiotics artisan synth stumptown gastropub cornhole
    <a class="ui-link" href="#visible-label">privacy policy ipsum</a>
    </span>
    </label>

    Label position

    <label class="ui-checkbox">
    <input name="checkbox-label-position" type="checkbox" />
    <span class="ui-label">Default</span>
    </label>
    <label class="ui-checkbox ui-stack">
    <input name="checkbox-label-position" type="checkbox" />
    <span class="ui-label">Stack</span>
    </label>

    End text

    <label class="ui-checkbox">
    <input
    name="checkbox-supporting-text"
    type="checkbox"
    aria-describedby="checkbox-supporting-text-end-text-1"
    />
    <span class="ui-label">Default</span>
    <span class="ui-end-text" id="checkbox-supporting-text-end-text-1"
    >Supporting text</span
    >
    </label>
    <label class="ui-checkbox ui-stack">
    <input
    name="checkbox-supporting-text"
    type="checkbox"
    aria-describedby="checkbox-supporting-text-end-text-2"
    />
    <span class="ui-label">Stack</span>
    <span class="ui-end-text" id="checkbox-supporting-text-end-text-2"
    >Supporting text</span
    >
    </label>

    Validation

    • Add [required] to the <input> element to toggle required styles.
    • Add data-invalid on the root element to toggle invalid styles. Make use of the end text to give extra feedback on the error.
    <div class="example-row ui-spacious">
    <label class="ui-checkbox">
    <input name="checkbox-validation" type="checkbox" required />
    <span class="ui-label">Default</span>
    </label>
    <label class="ui-checkbox ui-stack">
    <input name="checkbox-validation" type="checkbox" required />
    <span class="ui-label">Stack</span>
    </label>
    </div>
    <div class="example-row ui-spacious">
    <label class="ui-checkbox" data-invalid>
    <input
    name="checkbox-validation"
    type="checkbox"
    checked
    aria-describedby="checkbox-validation-end-text-1"
    />
    <span class="ui-label">Default</span>
    <span class="ui-end-text" id="checkbox-validation-end-text-1"
    >Check yourself</span
    >
    </label>
    <label class="ui-checkbox ui-stack" data-invalid>
    <input
    name="checkbox-validation"
    type="checkbox"
    aria-describedby="checkbox-validation-end-text-2"
    />
    <span class="ui-label">Stack</span>
    <span class="ui-end-text" id="checkbox-validation-end-text-2"
    >Before you wreck yourself</span
    >
    </label>
    </div>

    Indeterminate

    Add data-indeterminate to the <input type="checkbox"> and run a script that sets el.indeterminate = true. indeterminate is a JavaScript-only property on HTMLInputElement - the attribute alone has no effect.

    JavaScript required

    The indeterminate state cannot be set with HTML or CSS alone. The browser only exposes it as a property on HTMLInputElement, so a small script is needed to flip el.indeterminate = true after the element is in the DOM. The :indeterminate CSS pseudo-class then matches and the dash glyph appears.
    <fieldset class="ui-fieldset indeterminate-demo">
    <legend>
    <label class="ui-checkbox parent">
    <input type="checkbox" data-indeterminate />
    <span class="ui-label">Select all</span>
    </label>
    </legend>
    <div class="ui-field-group" role="group">
    <label class="ui-checkbox child">
    <input name="indeterminate-children" type="checkbox" checked />
    <span class="ui-label">Apples</span>
    </label>
    <label class="ui-checkbox child">
    <input name="indeterminate-children" type="checkbox" />
    <span class="ui-label">Bananas</span>
    </label>
    <label class="ui-checkbox child">
    <input name="indeterminate-children" type="checkbox" />
    <span class="ui-label">Cherries</span>
    </label>
    </div>
    </fieldset>
    <script>
    function setupIndeterminateDemoHtml() {
    document.querySelectorAll(".indeterminate-demo").forEach((root) => {
    const parent = root.querySelector('.parent input[type="checkbox"]')
    const children = Array.from(
    root.querySelectorAll('.child input[type="checkbox"]'),
    )
    if (!parent || children.length === 0) return
    const sync = () => {
    const checkedCount = children.filter((c) => c.checked).length
    parent.checked = checkedCount === children.length
    parent.indeterminate =
    checkedCount > 0 && checkedCount < children.length
    }
    parent.addEventListener("change", () => {
    children.forEach((c) => (c.checked = parent.checked))
    parent.indeterminate = false
    })
    children.forEach((c) => c.addEventListener("change", sync))
    sync()
    })
    }
    setupIndeterminateDemoHtml()
    document.addEventListener("astro:after-swap", setupIndeterminateDemoHtml)
    </script>

    Spread

    Add the .ui-spread class to the <label class="ui-checkbox">to push the label to the left and the checkbox to the right. This is useful for full-width items like lists and menus.

    <label class="ui-checkbox ui-spread">
    <input
    name="checkbox-spread"
    type="checkbox"
    aria-describedby="checkbox-spread-end-text-1"
    />
    <span class="ui-label">Accept Terms & Conditions</span>
    <span class="ui-end-text" id="checkbox-spread-end-text-1"
    >I have read and agree to the privacy policy.</span
    >
    </label>
    <label class="ui-checkbox ui-spread">
    <input
    name="checkbox-spread"
    type="checkbox"
    required
    aria-describedby="checkbox-spread-end-text-2"
    />
    <span class="ui-label">Required</span>
    <span class="ui-end-text" id="checkbox-spread-end-text-2"
    >You must accept this to continue.</span
    >
    </label>
    <label class="ui-checkbox ui-spread">
    <input
    name="checkbox-spread"
    type="checkbox"
    disabled
    aria-describedby="checkbox-spread-end-text-3"
    />
    <span class="ui-label">Disabled</span>
    <span class="ui-end-text" id="checkbox-spread-end-text-3"
    >This checkbox is disabled.</span
    >
    </label>
    <label class="ui-checkbox ui-spread" data-invalid>
    <input
    name="checkbox-spread"
    type="checkbox"
    aria-describedby="checkbox-spread-end-text-4"
    />
    <span class="ui-label">Invalid Checkbox</span>
    <span class="ui-end-text" id="checkbox-spread-end-text-4"
    >There is an error with this checkbox.</span
    >
    </label>

    Sizes

    <div class="example-row">
    <label class="ui-checkbox ui-small">
    <input name="checkbox-sizes" type="checkbox" checked />
    <span class="ui-sr-only">Label</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-sizes" type="checkbox" checked />
    <span class="ui-sr-only">Label</span>
    </label>
    <label class="ui-checkbox ui-large">
    <input name="checkbox-sizes" type="checkbox" checked />
    <span class="ui-sr-only">Label</span>
    </label>
    </div>
    <div class="example-row">
    <label class="ui-checkbox ui-small">
    <input name="checkbox-sizes" type="checkbox" checked />
    <span class="ui-label">Small</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-sizes" type="checkbox" checked />
    <span class="ui-label">Default</span>
    </label>
    <label class="ui-checkbox ui-large">
    <input name="checkbox-sizes" type="checkbox" checked />
    <span class="ui-label">Large</span>
    </label>
    </div>

    Field group

    Use field groups to group related checkboxes.

    Give every <input type="checkbox"> in the group the samename attribute so they're submitted together.

    See also: Form documentation.

    Legend
    <form class="ui-form">
    <fieldset class="ui-fieldset">
    <legend>Legend</legend>
    <div class="ui-field-group" role="group">
    <label class="ui-checkbox">
    <input name="checkbox-group" type="checkbox" checked />
    <span class="ui-label">Checkbox 1</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group" type="checkbox" />
    <span class="ui-label">Checkbox 2</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group" type="checkbox" />
    <span class="ui-label">Checkbox 3</span>
    </label>
    </div>
    </fieldset>
    </form>

    Direction

    Legend
    <form class="ui-form">
    <fieldset class="ui-fieldset">
    <legend>Legend</legend>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-checkbox">
    <input name="checkbox-group-direction" type="checkbox" checked />
    <span class="ui-label">Checkbox 1</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-direction" type="checkbox" />
    <span class="ui-label">Checkbox 2</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-direction" type="checkbox" />
    <span class="ui-label">Checkbox 3</span>
    </label>
    </div>
    </fieldset>
    </form>

    Field description

    Can be placed above and below the fields.

    Legend

    Field description above fields

    Legend

    Field description below fields

    <form class="ui-form">
    <fieldset class="ui-fieldset">
    <legend>Legend</legend>
    <p class="ui-field-description">Field description above fields</p>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-checkbox">
    <input
    name="checkbox-group-field-description-1"
    type="checkbox"
    checked
    />
    <span class="ui-label">Checkbox 1</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-field-description-1" type="checkbox" />
    <span class="ui-label">Checkbox 2</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-field-description-1" type="checkbox" />
    <span class="ui-label">Checkbox 3</span>
    </label>
    </div>
    </fieldset>
    <fieldset class="ui-fieldset">
    <legend>Legend</legend>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-checkbox">
    <input
    name="checkbox-group-field-description-2"
    type="checkbox"
    checked
    />
    <span class="ui-label">Checkbox 1</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-field-description-2" type="checkbox" />
    <span class="ui-label">Checkbox 2</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-field-description-2" type="checkbox" />
    <span class="ui-label">Checkbox 3</span>
    </label>
    </div>
    <p class="ui-field-description">Field description below fields</p>
    </fieldset>
    </form>

    Disabled

    Attach the disabled attribute to the <fieldset> element.

    Legend
    <form class="ui-form">
    <fieldset class="ui-fieldset" disabled>
    <legend>Legend</legend>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-checkbox">
    <input name="checkbox-group-disabled" type="checkbox" checked />
    <span class="ui-label">Checkbox 1</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-disabled" type="checkbox" />
    <span class="ui-label">Checkbox 2</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-disabled" type="checkbox" />
    <span class="ui-label">Checkbox 3</span>
    </label>
    </div>
    </fieldset>
    </form>

    Required

    Attach the required attribute to at least one of your <input> elements.

    These are required!
    <form class="ui-form">
    <fieldset class="ui-fieldset">
    <legend>These are required!</legend>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-checkbox">
    <input name="checkbox-group-required" type="checkbox" required />
    <span class="ui-label">Checkbox 1</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-required" type="checkbox" required />
    <span class="ui-label">Checkbox 2</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-required" type="checkbox" required />
    <span class="ui-label">Checkbox 3</span>
    </label>
    </div>
    </fieldset>
    </form>

    Validation

    Attach the data-invalid attribute to your <fieldset class="ui-fieldset"> element

    Legend
    Something went wrong!
    <form class="ui-form">
    <fieldset class="ui-fieldset" data-invalid>
    <legend>Legend</legend>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-checkbox">
    <input name="checkbox-group-validation" type="checkbox" checked />
    <span class="ui-label">Checkbox 1</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-validation" type="checkbox" />
    <span class="ui-label">Checkbox 2</span>
    </label>
    <label class="ui-checkbox">
    <input name="checkbox-group-validation" type="checkbox" />
    <span class="ui-label">Checkbox 3</span>
    </label>
    </div>
    <span class="ui-end-text">Something went wrong!</span>
    </fieldset>
    </form>

    Labels

    Accessible checkboxes must have a label. You can choose between three approaches:

    ApproachUsage in Checkbox component
    Provide a label text inside the label/role="checkbox" elementDefault
    Add a aria-label on the input elementNot used
    Have a visible label that you reference with aria-labelledbyNot used

    Keyboard support

    KeyFunction
    SpaceWhen Checkbox is focused it changes its state.
    Enter(Optional) When Checkbox is focused it changes its state.

    API

    Checkbox API

    TypeModifiersDefaultDescription
    Layout.ui-spread-Pushes the label and the input to opposite ends.
    Layout.ui-stack-Stacks the label under the input.
    Sizes.ui-large, .ui-small-The size of the element.
    Stateinput[data-indeterminate]-Shows a partially checked state. Sets the indeterminate property on the <input>.
    Validation[data-invalid]-Shows error styles.

    Parts

    PartDescription
    label.ui-checkboxContainer element.
    <input>The checkbox input.
    .ui-labelThe label.
    .ui-end-textSupporting text displayed below the label.

    Use .ui-sr-only instead of .ui-label to hide the label visually. data-indeterminate needs checkbox.js, which sets the indeterminate property.

    Field group API

    TypeModifiersDefaultDescription
    Orientationdefault, .ui-row-The orientation of the element.

    Parts

    PartDescription
    .ui-field-groupContainer element.

    The root needs role="group". Wrap it in a .ui-fieldset with a <legend> to label it.

    Browser support

    Full supportSupported since v105.Full supportSupported since v121.Full supportSupported since v15.4.

    See also the full browser support guide.

    Installation

    See also

    @layer components.root {
    label.ui-checkbox {
    --_input-size: var(--size-4);
    align-items: center;
    color: var(--text-primary);
    cursor: pointer;
    display: inline-grid;
    gap: 0 var(--size-2);
    grid-auto-columns: auto;
    grid-auto-flow: column;
    inline-size: fit-content;
    line-height: 1.5;
    transform: translateZ(0);
    user-select: none;
    /* Disabled */
    &:has([disabled]) {
    cursor: not-allowed;
    opacity: 0.64;
    user-select: none;
    input {
    cursor: not-allowed;
    }
    }
    /* Required dot */
    &:has(:invalid) {
    .ui-label:after {
    color: var(--red);
    content: "*";
    inset: 0 -0.25ex auto auto;
    position: absolute;
    }
    }
    /* Label */
    .ui-label {
    color: var(--text-primary);
    font-size: var(--font-size-05);
    grid-column: 2;
    grid-row: 1;
    padding-inline: 0 1ex;
    position: relative;
    }
    /* End text */
    :where(.ui-end-text) {
    color: var(--text-muted);
    font-size: var(--font-size-0);
    grid-column: 2;
    grid-row: 2;
    line-height: 1.5;
    z-index: 1;
    }
    /* Spread layout */
    &.ui-spread {
    align-items: center;
    column-gap: var(--size-4);
    grid-auto-flow: unset;
    grid-template-columns: 1fr auto;
    inline-size: 100%;
    .ui-label {
    font-weight: 600;
    grid-column: 1;
    grid-row: 1;
    inline-size: fit-content;
    }
    input {
    grid-column: 2;
    grid-row: 1;
    }
    :where(.ui-end-text) {
    grid-column: 1;
    grid-row: 2;
    }
    }
    /* Stacked layout */
    &.ui-stack {
    grid-auto-columns: unset;
    justify-items: center;
    .ui-label {
    grid-column: 1/-1;
    grid-row: 2;
    margin-block-start: var(--size-1);
    padding-inline: 1ex;
    /* Required dot */
    &::after {
    inset: 0 -0.25ex auto auto;
    }
    }
    .ui-end-text {
    grid-column: 1/-1;
    grid-row: 3;
    }
    }
    /* Input */
    input[type="checkbox"] {
    --_input-size: var(--size-4);
    appearance: none;
    aspect-ratio: 1;
    background-color: var(--surface-default);
    block-size: var(--_input-size);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-1);
    box-sizing: border-box;
    cursor: pointer;
    display: grid;
    font-size: var(--_input-size);
    inline-size: var(--_input-size);
    margin: 0;
    padding: 0;
    place-items: center;
    position: relative;
    &:checked,
    &:indeterminate {
    background-color: var(--primary);
    border-color: var(--primary);
    }
    /* Checkmark */
    &::after {
    background-color: var(--primary-contrast);
    clip-path: polygon(
    15% 52%,
    40% 77%,
    85% 32%,
    75% 22%,
    40% 57%,
    25% 42%
    );
    content: "";
    inset: 0;
    opacity: 0;
    position: absolute;
    }
    &:checked::after,
    &:indeterminate::after {
    opacity: 1;
    }
    /* Indeterminate dash */
    &:indeterminate::after {
    clip-path: polygon(20% 45%, 80% 45%, 80% 55%, 20% 55%);
    }
    &::before {
    --highlight-size: 175%;
    }
    }
    /* Sizes */
    &.ui-small {
    input[type="checkbox"] {
    --_input-size: var(--size-3);
    }
    }
    &.ui-large {
    input[type="checkbox"] {
    --_input-size: var(--size-5);
    }
    }
    /* Validation */
    &[data-invalid],
    &:has(:user-invalid) {
    --primary: var(--critical);
    :where(.ui-end-text) {
    color: var(--critical);
    }
    }
    /* Touch devices */
    @media (pointer: coarse) {
    input {
    --_input-size: var(--size-4);
    }
    }
    @media (forced-colors: active) {
    input {
    border: 1px solid CanvasText;
    &:checked,
    &:indeterminate {
    background-color: SelectedItem;
    border-color: SelectedItem;
    &::after {
    background-color: SelectedItemText;
    }
    }
    }
    }
    }
    }
    @layer components.extended {
    /* Form */
    :where(.ui-form) {
    display: grid;
    gap: var(--size-8);
    hr {
    margin-block: 0;
    }
    }
    /* Fieldset */
    :where(.ui-fieldset) {
    all: unset;
    border: 0;
    border-radius: 0;
    display: grid;
    gap: var(--size-1);
    margin: 0;
    min-inline-size: 0;
    padding: 0;
    /* Legend */
    :where(legend, .ui-legend) {
    all: unset;
    color: var(--text-primary);
    font-weight: 600;
    margin-block-end: var(--size-3);
    padding: 0;
    &:has(+ :where(.ui-field-description)) {
    margin-block-end: 0;
    }
    }
    /* Field description / supporting text */
    :where(.ui-field-description) {
    color: var(--text-muted);
    font-size: var(--font-size-05);
    line-height: var(--font-lineheight-3);
    &:has(+ *) {
    margin-block-end: var(--size-3);
    }
    }
    /* End text */
    :where(.ui-end-text) {
    color: var(--text-muted);
    font-size: var(--font-size-0);
    line-height: var(--font-lineheight-3);
    }
    &:has(.ui-text-field.ui-row) {
    row-gap: var(--size-7);
    }
    /* Disabled */
    &[disabled] {
    opacity: 0.64;
    user-select: none;
    input,
    label,
    .ui-label {
    cursor: not-allowed;
    }
    }
    /* Error / validation */
    &[data-invalid] {
    :where(.ui-end-text) {
    color: var(--critical);
    }
    :where(.ui-checkbox, .ui-radio, .ui-switch) {
    --primary: var(--critical);
    :where(.ui-end-text) {
    color: var(--critical);
    }
    }
    :where(.ui-switch) {
    input {
    border-radius: var(--radius-round);
    outline: 2px solid var(--critical);
    }
    }
    }
    /* Required */
    &:has(:invalid) {
    :where(legend, .ui-legend) {
    padding-inline-end: 1ex;
    position: relative;
    &::after {
    color: var(--red);
    content: "*";
    inset: 0 -0.25ex auto auto;
    position: absolute;
    }
    }
    }
    }
    /* Field group */
    :where(.ui-field-group) {
    display: flex;
    flex-direction: column;
    gap: var(--size-4);
    /* If it only has checkboxes, radios, or switches */
    &:has(> :where(.ui-checkbox, .ui-radio, .ui-switch)):not(
    :has(> :not(.ui-checkbox, .ui-radio, .ui-switch))
    ) {
    gap: var(--size-2);
    }
    /* If it only has buttons */
    &:has(.ui-button):not(:has(*:not(.ui-button))) {
    align-items: center;
    flex-direction: row;
    gap: var(--size-2);
    /* If it's not preceded by an hr */
    &:not(hr + &) {
    margin-block-start: var(--size-4);
    }
    }
    & + & {
    margin-block-start: var(--size-5);
    }
    /* Directions */
    &.ui-row {
    flex-direction: row;
    flex-wrap: wrap;
    &:has(> :where(.ui-checkbox, .ui-radio, .ui-switch)) {
    gap: var(--size-4);
    }
    }
    }
    }