Skip to content

Checkbox

A native <input type="checkbox"> styled via class + data attributes from the optional styles layer. Two variants, three sizes, color theming, high-contrast and disabled states. Checkmark uses a Unicode glyph (✓ / −), recolored via currentColor — no SVG, no JS.

Install

import "elements-kit/ui/styles/theme.css";
import "elements-kit/ui/styles/scaling.css";
import "elements-kit/ui/styles/radius.css";
import "elements-kit/ui/styles/space.css";
import "elements-kit/ui/styles/typography.css";
import "elements-kit/ui/styles/cursor.css";
import "elements-kit/ui/styles/unset.css";
// pick a neutral palette for --neutral-* (must match data-neutral on root):
import "elements-kit/ui/styles/palette/gray.css";
import "elements-kit/ui/styles/neutral/gray.css";
// import any color scales you want to use for accent theming:
import "elements-kit/ui/styles/palette/mint.css";
import "elements-kit/ui/styles/accent/mint.css";
// and the checkbox itself:
import "elements-kit/ui/checkbox/checkbox.css";

See Styles for the full token system, accent/gray scale lists, and theming knobs.

API

<input
type="checkbox"
class="unset x-checkbox"
data-variant="surface"
data-size="2"
/>

The unset class (Styles → Unset native styles) clears the browser’s default <input> rendering so .x-checkbox styles render predictably. Skip it and you’ll see the OS-native checkbox leak through.

AttributeValues
data-variantsurface (default), soft
data-size1, 2 (default), 3
data-accent (on a parent or the input)any imported color scale (mint, blue, iris, …)
data-high-contrastmodifier — boosts contrast against the page background
disabled / data-disablednative :disabled state, or data-disabled on non-input elements

Sizing

data-sizeboxindicatorradius
1--space-4 × 0.875 (~14px)9px × --scaling--radius-1 × 0.875
2 (default)--space-4 (~16px)10px × --scaling--radius-1
3--space-4 × 1.25 (~20px)12px × --scaling--radius-1 × 1.25

--scaling on <html> scales the indicator with the rest of the type system.

Variants

  • surface (default) — 1px hairline border using --neutral-a7. Background fills with --accent-9 and contrast indicator on :checked / :indeterminate.
  • soft — tinted background using --accent-a5 at every state. Indicator uses --accent-a11 so the check reads at low emphasis.

States

  • :checked — renders (U+2713) in the indicator slot.
  • :indeterminate — renders (U+2212). The browser doesn’t expose this via HTML — set it from JS (el.indeterminate = true) and CSS picks it up.
  • :disabled / [data-disabled] — muted border + muted indicator color, no hover changes.
  • :focus-visible — 2px --focus-8 outline at +2px offset.

With a label

.x-checkbox is just an input — wrap it in a <label> (or pair via for=) to make text clickable too.

<label style="display: inline-flex; align-items: center; gap: 0.5em;">
<input type="checkbox" class="unset x-checkbox" />
<span>Subscribe to updates</span>
</label>

For multiple options stack labels in a flex column with gap: var(--space-1). The kit deliberately doesn’t ship a .x-checkbox-group class — flex + gap is one line.

Theming

Set data-accent="<color>" on the input or any ancestor (e.g. <body>) to theme the accent fill. Light/dark flips automatically via the .dark class on a parent — see Light & dark.

<body data-accent="iris">
<input type="checkbox" class="unset x-checkbox" checked />
</body>

Accessibility

Pair every checkbox with a <label> — either by wrapping the input or by using <label for="…">. Indeterminate has no built-in screen-reader announcement; if the tri-state is semantically meaningful, add aria-checked="mixed" alongside setting el.indeterminate = true.