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

    • <Checkbox>

      Container element.

    • <input>

      The checkbox input.

    • slot="default"

      The label.

    • slot="end-text"

      Supporting text displayed below the label.

    ---
    import { Checkbox } from "@opui/astro"
    ---
    <Checkbox checked name="checkbox-variants" hideLabel>Checked</Checkbox>
    <Checkbox name="checkbox-variants" hideLabel>Unchecked</Checkbox>
    <Checkbox indeterminate name="checkbox-variants" hideLabel
    >Indeterminate</Checkbox
    >
    <Checkbox disabled name="checkbox-variants" hideLabel>Disabled</Checkbox>
    <Checkbox checked disabled name="checkbox-variants" hideLabel
    >Checked and disabled</Checkbox
    >
    <label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-variants" checked /><span
    class="ui-sr-only"
    >Checked</span
    ></label
    ><label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-variants" /><span class="ui-sr-only"
    >Unchecked</span
    ></label
    ><label class="ui-checkbox"
    ><input type="checkbox" data-indeterminate name="checkbox-variants" /><span
    class="ui-sr-only"
    >Indeterminate</span
    ></label
    ><label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-variants" disabled /><span
    class="ui-sr-only"
    >Disabled</span
    ></label
    ><label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-variants" 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.

    ---
    import { Checkbox } from "@opui/astro"
    ---
    <Checkbox checked name="checkbox-visible-label">Choice A</Checkbox>
    <Checkbox disabled name="checkbox-visible-label">Disabled</Checkbox>
    <Checkbox checked disabled name="checkbox-visible-label"
    >Checked and disabled</Checkbox
    >
    <Checkbox name="checkbox-visible-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>
    </Checkbox>
    <label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-visible-label" checked /><span
    class="ui-label"
    >Choice A</span
    ></label
    ><label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-visible-label" disabled /><span
    class="ui-label"
    >Disabled</span
    ></label
    ><label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-visible-label" checked disabled /><span
    class="ui-label"
    >Checked and disabled</span
    ></label
    ><label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-visible-label" /><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

    ---
    import { Checkbox } from "@opui/astro"
    ---
    <Checkbox name="checkbox-label-position">Default</Checkbox>
    <Checkbox stack name="checkbox-label-position">Stack</Checkbox>
    <label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-label-position" /><span
    class="ui-label"
    >Default</span
    ></label
    ><label class="ui-checkbox ui-stack"
    ><input type="checkbox" name="checkbox-label-position" /><span
    class="ui-label"
    >Stack</span
    ></label
    >

    End text

    ---
    import { Checkbox } from "@opui/astro"
    ---
    <Checkbox name="checkbox-supporting-text">
    Default
    <Fragment slot="end-text">Supporting text</Fragment>
    </Checkbox>
    <Checkbox stack name="checkbox-supporting-text">
    Stack
    <Fragment slot="end-text">Supporting text</Fragment>
    </Checkbox>
    <label class="ui-checkbox"
    ><input
    type="checkbox"
    aria-describedby="end-text-2"
    name="checkbox-supporting-text"
    /><span class="ui-label">Default</span
    ><span id="end-text-2" class="ui-end-text">Supporting text</span></label
    ><label class="ui-checkbox ui-stack"
    ><input
    type="checkbox"
    aria-describedby="end-text-3"
    name="checkbox-supporting-text"
    /><span class="ui-label">Stack</span
    ><span id="end-text-3" class="ui-end-text">Supporting text</span></label
    >

    Validation

    • Set required on the component to toggle required styles on the input.
    • Use the error prop to toggle invalid styles. It rendersdata-invalid on the root element. Make use of the end text to give extra feedback on the error.
    ---
    import { Checkbox } from "@opui/astro"
    ---
    <div class="example-row ui-spacious">
    <Checkbox required name="checkbox-validation">Default</Checkbox>
    <Checkbox stack required name="checkbox-validation">Stack</Checkbox>
    </div>
    <div class="example-row ui-spacious">
    <Checkbox error checked name="checkbox-validation">
    Default
    <Fragment slot="end-text">Check yourself</Fragment>
    </Checkbox>
    <Checkbox stack error name="checkbox-validation">
    Stack
    <Fragment slot="end-text">Before you wreck yourself</Fragment>
    </Checkbox>
    </div>
    <div class="example-row ui-spacious">
    <label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-validation" required /><span
    class="ui-label"
    >Default</span
    ></label
    ><label class="ui-checkbox ui-stack"
    ><input type="checkbox" name="checkbox-validation" required /><span
    class="ui-label"
    >Stack</span
    ></label
    >
    </div>
    <div class="example-row ui-spacious">
    <label class="ui-checkbox" data-invalid
    ><input
    type="checkbox"
    aria-describedby="end-text-4"
    name="checkbox-validation"
    checked
    /><span class="ui-label">Default</span
    ><span id="end-text-4" class="ui-end-text">Check yourself</span></label
    ><label class="ui-checkbox ui-stack" data-invalid
    ><input
    type="checkbox"
    aria-describedby="end-text-5"
    name="checkbox-validation"
    /><span class="ui-label">Stack</span
    ><span id="end-text-5" class="ui-end-text"
    >Before you wreck yourself</span
    ></label
    >
    </div>

    Indeterminate

    Set the indeterminate prop to render a partially-selected state.indeterminate is a JavaScript-only property on HTMLInputElement, so the component renders data-indeterminate and applies the property at runtime.

    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.
    ---
    import { Checkbox, FieldGroup, FieldLegend, FieldSet } from "@opui/astro"
    ---
    <FieldSet class="indeterminate-demo">
    <FieldLegend>
    <Checkbox class="parent" indeterminate>Select all</Checkbox>
    </FieldLegend>
    <FieldGroup name="indeterminate-children">
    <Checkbox class="child" checked>Apples</Checkbox>
    <Checkbox class="child">Bananas</Checkbox>
    <Checkbox class="child">Cherries</Checkbox>
    </FieldGroup>
    </FieldSet>
    <script>
    function setupIndeterminateDemo() {
    document
    .querySelectorAll<HTMLElement>(".indeterminate-demo")
    .forEach((root) => {
    const parent = root.querySelector<HTMLInputElement>(
    '.parent input[type="checkbox"]',
    )
    const children = Array.from(
    root.querySelectorAll<HTMLInputElement>(
    '.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()
    })
    }
    setupIndeterminateDemo()
    document.addEventListener("astro:after-swap", setupIndeterminateDemo)
    </script>
    <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 />
    <script type="module">
    function e(e = document) {
    e.querySelectorAll(
    `input[type="checkbox"][data-indeterminate]`,
    ).forEach((e) => {
    e.indeterminate = !0;
    });
    }
    function t() {
    (e(), document.addEventListener(`astro:after-swap`, () => e()));
    }
    t();
    </script>
    <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 type="module">
    function e() {
    document.querySelectorAll(`.indeterminate-demo`).forEach((e) => {
    let t = e.querySelector(`.parent input[type="checkbox"]`),
    n = Array.from(e.querySelectorAll(`.child input[type="checkbox"]`));
    if (!t || n.length === 0) return;
    let r = () => {
    let e = n.filter((e) => e.checked).length;
    ((t.checked = e === n.length),
    (t.indeterminate = e > 0 && e < n.length));
    };
    (t.addEventListener(`change`, () => {
    (n.forEach((e) => (e.checked = t.checked)), (t.indeterminate = !1));
    }),
    n.forEach((e) => e.addEventListener(`change`, r)),
    r());
    });
    }
    (e(), document.addEventListener(`astro:after-swap`, e));
    </script>

    Spread

    Use the spread prop to push the label to the left and the checkbox to the right. This is useful for full-width items like lists and menus.

    ---
    import { Checkbox } from "@opui/astro"
    ---
    <Checkbox name="checkbox-spread" spread>
    Accept Terms & Conditions
    <Fragment slot="end-text"
    >I have read and agree to the privacy policy.</Fragment
    >
    </Checkbox>
    <Checkbox name="checkbox-spread" spread required>
    Required
    <Fragment slot="end-text">You must accept this to continue.</Fragment>
    </Checkbox>
    <Checkbox name="checkbox-spread" spread disabled>
    Disabled
    <Fragment slot="end-text">This checkbox is disabled.</Fragment>
    </Checkbox>
    <Checkbox name="checkbox-spread" spread error>
    Invalid Checkbox
    <Fragment slot="end-text">There is an error with this checkbox.</Fragment>
    </Checkbox>
    <label class="ui-checkbox ui-spread"
    ><input
    type="checkbox"
    aria-describedby="end-text-6"
    name="checkbox-spread"
    /><span class="ui-label">Accept Terms & Conditions</span
    ><span id="end-text-6" class="ui-end-text"
    >I have read and agree to the privacy policy.</span
    ></label
    ><label class="ui-checkbox ui-spread"
    ><input
    type="checkbox"
    aria-describedby="end-text-7"
    name="checkbox-spread"
    required
    /><span class="ui-label">Required</span
    ><span id="end-text-7" class="ui-end-text"
    >You must accept this to continue.</span
    ></label
    ><label class="ui-checkbox ui-spread"
    ><input
    type="checkbox"
    aria-describedby="end-text-8"
    name="checkbox-spread"
    disabled
    /><span class="ui-label">Disabled</span
    ><span id="end-text-8" class="ui-end-text"
    >This checkbox is disabled.</span
    ></label
    ><label class="ui-checkbox ui-spread" data-invalid
    ><input
    type="checkbox"
    aria-describedby="end-text-9"
    name="checkbox-spread"
    /><span class="ui-label">Invalid Checkbox</span
    ><span id="end-text-9" class="ui-end-text"
    >There is an error with this checkbox.</span
    ></label
    >

    Sizes

    ---
    import { Checkbox } from "@opui/astro"
    ---
    <div class="example-row">
    <Checkbox hideLabel size="small" checked name="checkbox-sizes">Label</Checkbox
    >
    <Checkbox hideLabel checked name="checkbox-sizes">Label</Checkbox>
    <Checkbox hideLabel size="large" checked name="checkbox-sizes">Label</Checkbox
    >
    </div>
    <div class="example-row">
    <Checkbox size="small" checked name="checkbox-sizes">Small</Checkbox>
    <Checkbox checked name="checkbox-sizes">Default</Checkbox>
    <Checkbox size="large" checked name="checkbox-sizes">Large</Checkbox>
    </div>
    <div class="example-row">
    <label class="ui-checkbox ui-small"
    ><input type="checkbox" name="checkbox-sizes" checked /><span
    class="ui-sr-only"
    >Label</span
    ></label
    ><label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-sizes" checked /><span
    class="ui-sr-only"
    >Label</span
    ></label
    ><label class="ui-checkbox ui-large"
    ><input type="checkbox" name="checkbox-sizes" checked /><span
    class="ui-sr-only"
    >Label</span
    ></label
    >
    </div>
    <div class="example-row">
    <label class="ui-checkbox ui-small"
    ><input type="checkbox" name="checkbox-sizes" checked /><span
    class="ui-label"
    >Small</span
    ></label
    ><label class="ui-checkbox"
    ><input type="checkbox" name="checkbox-sizes" checked /><span
    class="ui-label"
    >Default</span
    ></label
    ><label class="ui-checkbox ui-large"
    ><input type="checkbox" name="checkbox-sizes" checked /><span
    class="ui-label"
    >Large</span
    ></label
    >
    </div>

    Field group

    Use field groups to group related checkboxes.

    The name prop will get passed down to each checkbox in the group.

    See also: Form documentation.

    Legend
    ---
    import { Checkbox } from "@opui/astro"
    import { FieldSet } from "@opui/astro"
    import { FieldLegend } from "@opui/astro"
    import { FieldGroup } from "@opui/astro"
    import { Form } from "@opui/astro"
    ---
    <Form>
    <FieldSet>
    <FieldLegend>Legend</FieldLegend>
    <FieldGroup name="checkbox-group">
    <Checkbox checked>Checkbox 1</Checkbox>
    <Checkbox>Checkbox 2</Checkbox>
    <Checkbox>Checkbox 3</Checkbox>
    </FieldGroup>
    </FieldSet>
    </Form>
    <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
    ---
    import { Checkbox } from "@opui/astro"
    import { FieldSet } from "@opui/astro"
    import { FieldLegend } from "@opui/astro"
    import { FieldGroup } from "@opui/astro"
    import { Form } from "@opui/astro"
    ---
    <Form>
    <FieldSet>
    <FieldLegend>Legend</FieldLegend>
    <FieldGroup direction="row" name="checkbox-group-direction">
    <Checkbox checked>Checkbox 1</Checkbox>
    <Checkbox>Checkbox 2</Checkbox>
    <Checkbox>Checkbox 3</Checkbox>
    </FieldGroup>
    </FieldSet>
    </Form>
    <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

    ---
    import { Checkbox } from "@opui/astro"
    import { FieldSet } from "@opui/astro"
    import { FieldLegend } from "@opui/astro"
    import { FieldDescription } from "@opui/astro"
    import { FieldGroup } from "@opui/astro"
    import { Form } from "@opui/astro"
    ---
    <Form>
    <FieldSet>
    <FieldLegend>Legend</FieldLegend>
    <FieldDescription>Field description above fields</FieldDescription>
    <FieldGroup direction="row" name="checkbox-group-field-description-1">
    <Checkbox checked>Checkbox 1</Checkbox>
    <Checkbox>Checkbox 2</Checkbox>
    <Checkbox>Checkbox 3</Checkbox>
    </FieldGroup>
    </FieldSet>
    <FieldSet>
    <FieldLegend>Legend</FieldLegend>
    <FieldGroup direction="row" name="checkbox-group-field-description-2">
    <Checkbox checked>Checkbox 1</Checkbox>
    <Checkbox>Checkbox 2</Checkbox>
    <Checkbox>Checkbox 3</Checkbox>
    </FieldGroup>
    <FieldDescription>Field description below fields</FieldDescription>
    </FieldSet>
    </Form>
    <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
    ---
    import { Checkbox } from "@opui/astro"
    import { FieldSet } from "@opui/astro"
    import { FieldLegend } from "@opui/astro"
    import { FieldGroup } from "@opui/astro"
    import { Form } from "@opui/astro"
    ---
    <Form>
    <FieldSet disabled>
    <FieldLegend>Legend</FieldLegend>
    <FieldGroup direction="row" name="checkbox-group-disabled">
    <Checkbox checked>Checkbox 1</Checkbox>
    <Checkbox>Checkbox 2</Checkbox>
    <Checkbox>Checkbox 3</Checkbox>
    </FieldGroup>
    </FieldSet>
    </Form>
    <form class="ui-form">
    <fieldset disabled class="ui-fieldset">
    <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!
    ---
    import { Checkbox } from "@opui/astro"
    import { FieldSet } from "@opui/astro"
    import { FieldLegend } from "@opui/astro"
    import { FieldGroup } from "@opui/astro"
    import { Form } from "@opui/astro"
    ---
    <Form>
    <FieldSet>
    <FieldLegend>These are required!</FieldLegend>
    <FieldGroup direction="row" name="checkbox-group-required">
    <Checkbox required>Checkbox 1</Checkbox>
    <Checkbox required>Checkbox 2</Checkbox>
    <Checkbox required>Checkbox 3</Checkbox>
    </FieldGroup>
    </FieldSet>
    </Form>
    <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 component.

    Legend
    Something went wrong!
    ---
    import { Checkbox } from "@opui/astro"
    import { FieldSet } from "@opui/astro"
    import { FieldLegend } from "@opui/astro"
    import { FieldGroup } from "@opui/astro"
    import { Form } from "@opui/astro"
    ---
    <Form>
    <FieldSet data-invalid="">
    <FieldLegend>Legend</FieldLegend>
    <FieldGroup direction="row" name="checkbox-group-validation">
    <Checkbox checked>Checkbox 1</Checkbox>
    <Checkbox>Checkbox 2</Checkbox>
    <Checkbox>Checkbox 3</Checkbox>
    </FieldGroup>
    <span class="ui-end-text">Something went wrong!</span>
    </FieldSet>
    </Form>
    <form class="ui-form">
    <fieldset data-invalid class="ui-fieldset">
    <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

    PropTypeDefaultDescription
    errorbooleanfalseShows error styles.
    hideLabelbooleanfalseVisually hides the label.
    indeterminatebooleanfalseShows a partially checked state. Sets the indeterminate property on the <input>.
    size"small", "large"-The size of the element.
    spreadbooleanfalsePushes the label and the input to opposite ends.
    stackbooleanfalseStacks the label under the input.

    Slots

    SlotDescription
    defaultThe label.
    end-textSupporting text displayed below the label.

    Other attributes, such as checked, disabled, name and required, go to the <input>.

    Field group API

    PropTypeDefaultDescription
    direction"row", "column"-The orientation of the element.
    namestring-Sets name on every input, select and textarea inside.

    Slots

    SlotDescription
    defaultThe fields, such as checkboxes, radios or switches.

    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);
    }
    }
    }
    }