---
outline: deep
---

# Checkbox

Checkboxes let users select one or more options, or toggle a single setting on or off.

**`.l-checkbox`** — Native HTML Element

```html
<l-form-field>
  <label>Subscribe to the newsletter</label>
  <input type="checkbox" />
  <p class="l-hint">One email a month, unsubscribe anytime.</p>
</l-form-field>
```

[`l-form-field`](/elements/form-field) auto-styles a bare `<input type="checkbox">` and wires the accessibility (label, hint, error, `aria-*`). Standalone, apply `.l-checkbox` to the input yourself.

For a single setting that takes effect **immediately** (no Save button), use a switch instead.

## Options

### Checked

Native `checked` attribute.

### Disabled

Native `disabled` attribute.

### States

```html
<div class="flex flex-col gap-3">
  <l-form-field>
    <label>Unchecked</label>
    <input type="checkbox" />
  </l-form-field>
  <l-form-field>
    <label>Checked</label>
    <input
      type="checkbox"
      checked
    />
  </l-form-field>
  <l-form-field>
    <label>Indeterminate</label>
    <input
      type="checkbox"
      id="demo-indeterminate"
    />
  </l-form-field>
  <l-form-field>
    <label>Disabled</label>
    <input
      type="checkbox"
      disabled
    />
  </l-form-field>
  <l-form-field>
    <label>Disabled checked</label>
    <input
      type="checkbox"
      checked
      disabled
    />
  </l-form-field>
  <l-form-field invalid>
    <label>Invalid (required, unchecked)</label>
    <input
      type="checkbox"
      required
    />
  </l-form-field>
</div>
```

### Invalid

Styled via `:user-invalid` (after interaction) or by setting `aria-invalid="true"`. Inside `l-form-field` this is managed for you.

### Size & accent

Override `--size` for the box and `--accent` for the checked fill.

```html
<div class="flex flex-col gap-3">
  <l-form-field>
    <label>Default</label>
    <input
      type="checkbox"
      checked
    />
  </l-form-field>
  <l-form-field>
    <label>Large</label>
    <input
      type="checkbox"
      class="[--size:1.5rem]"
      checked
    />
  </l-form-field>
  <l-form-field>
    <label>Extra large, dark accent</label>
    <input
      type="checkbox"
      class="[--size:2rem] [--accent:var(--l-color-gray-900)]"
      checked
    />
  </l-form-field>
</div>
```

## Examples

### With a hint

`.l-hint` adds always-visible helper text, linked to the control via `aria-describedby`.

```html
<l-form-field>
  <label>Subscribe to the newsletter</label>
  <input type="checkbox" />
  <p class="l-hint">One email a month, unsubscribe anytime.</p>
</l-form-field>
```

### With an error

`.l-error` holds the validation message — hidden until the field is invalid, then revealed with `aria-invalid` and announced (`role="alert"`). `invalid` on the field forces the state here for the preview.

```html
<l-form-field invalid>
  <label>I accept the terms and conditions</label>
  <input
    type="checkbox"
    required
  />
  <p class="l-hint">Read them before checking this box.</p>
  <p class="l-error">You must accept the terms to continue.</p>
</l-form-field>
```

## Accessibility

### Criteria

- **Role** — Uses native `<input type=checkbox>` — built-in `checkbox` semantics and `checked`/`mixed` states
- **Accessible name** — Must have an associated `<label>` (wrap the input or use `for`/`id`)
- **Target size** — The label is part of the click target; keep the interactive area at least 24×24px
- **Focus visible** — Keyboard focus shows a 2px outline via `:focus-visible`
- **Required state** — Native `required` communicates a mandatory field to assistive tech

### Rules

- Always pair the checkbox with a `<label>` — wrap the input or link with `for`/`id`
- Use `indeterminate` only for the parent of a group, never as a third user-selectable value
- For a single setting applied immediately, use a switch instead of a checkbox

### Keyboard interactions

- `Space` — Toggles the checkbox
- `Tab` — Moves focus to the next focusable element

## API reference

### Importing

```css
@import 'luxen-ui/css/checkbox';
```

### Attributes & Properties

- **checked** — Whether the checkbox is checked.
- **disabled** — Disables the checkbox.
- **required** — Marks the checkbox as required for form submission.
- **indeterminate** — Indeterminate state (DOM property `el.indeterminate = true`; renders a dash). Typically the parent of a group.
- **aria-invalid** — Set to `true` to force the invalid style (otherwise applied via `:user-invalid`). `l-form-field` manages this automatically.

### CSS classes

- `.l-checkbox` — Base checkbox style, applied to `<input type="checkbox">`. Inside `l-form-field` a bare checkbox is auto-styled, so the class is optional there.

### CSS custom properties

- `--size` (default: `1.25em`) — Box size.
- `--accent` (default: `var(--l-form-control-activated-color)`) — Checked/indeterminate fill color.
- `--checkmark` — Checkmark icon as a `url()`. Override to swap the SVG (color is baked into the image).
