Checkbox
A Tailwind CSS checkbox component for toggling options on and off.
<input type="checkbox" class="checkbox" />With label
Pair with a Label and wrap in a Field for accessible form fields. Connect them using matching for and id attributes so clicking the label toggles the checkbox and screen readers announce it correctly.
<div class="w-fit">
<div class="field field-horizontal">
<input
type="checkbox"
class="checkbox"
id="accept-terms-and-conditions"
name="accept-terms-and-conditions"
/>
<label class="label" for="accept-terms-and-conditions">
Accept terms and conditions
</label>
</div>
</div>Group
Use multiple checkboxes with the same name for multi-select groups.
<div class="w-fit">
<div class="field-group">
<span class="label">Dietary requirements</span>
<div class="field-group gap-3">
<div class="field field-horizontal">
<input
type="checkbox"
class="checkbox"
id="dietary-requirements-vegetarian"
name="dietary-requirements"
checked=""
value="vegetarian"
/>
<label class="label" for="dietary-requirements-vegetarian">
Vegetarian
</label>
</div>
<div class="field field-horizontal">
<input
type="checkbox"
class="checkbox"
id="dietary-requirements-vegan"
name="dietary-requirements"
value="vegan"
/>
<label class="label" for="dietary-requirements-vegan">Vegan</label>
</div>
<div class="field field-horizontal">
<input
type="checkbox"
class="checkbox"
id="dietary-requirements-gluten-free"
name="dietary-requirements"
value="gluten-free"
/>
<label class="label" for="dietary-requirements-gluten-free">
Gluten-free
</label>
</div>
<div class="field field-horizontal">
<input
type="checkbox"
class="checkbox"
id="dietary-requirements-dairy-free"
name="dietary-requirements"
value="dairy-free"
/>
<label class="label" for="dietary-requirements-dairy-free">
Dairy-free
</label>
</div>
</div>
</div>
</div>With descriptions
Add a description below each label for extra context.
Receive updates about your account via email.
Get text messages for important alerts.
Receive push notifications on your device.
<div class="w-fit">
<div class="field-group">
<span class="label">Notifications</span>
<div class="field-group">
<div class="field field-horizontal">
<input
type="checkbox"
class="checkbox"
id="notifications-email"
name="notifications"
value="email"
/>
<div class="field-content">
<label class="label" for="notifications-email">
Email notifications
</label>
<p class="field-description">
Receive updates about your account via email.
</p>
</div>
</div>
<div class="field field-horizontal">
<input
type="checkbox"
class="checkbox"
id="notifications-sms"
name="notifications"
value="sms"
/>
<div class="field-content">
<label class="label" for="notifications-sms">SMS notifications</label>
<p class="field-description">Get text messages for important alerts.</p>
</div>
</div>
<div class="field field-horizontal">
<input
type="checkbox"
class="checkbox"
id="notifications-push"
name="notifications"
value="push"
/>
<div class="field-content">
<label class="label" for="notifications-push">Push notifications</label>
<p class="field-description">
Receive push notifications on your device.
</p>
</div>
</div>
</div>
</div>
</div>Disabled
Add disabled to the checkbox and peer so the label dims to match.
<div class="w-fit">
<div class="field field-horizontal">
<input type="checkbox" class="checkbox peer" id="disabled-cb" disabled="" />
<label class="label" for="disabled-cb">Disabled checkbox</label>
</div>
</div>Card select
Use checkboxes inside cards for a visual multi-select layout.
<div class="w-full max-w-md">
<div class="grid gap-3">
<span class="label">Platform</span>
<div class="grid gap-5" style="grid-template-columns: repeat(3, 1fr)">
<label
class="relative flex flex-col items-center gap-3 p-4 border rounded-lg cursor-pointer has-checked:border-primary has-checked:bg-primary/[2.5%]"
>
<input
type="checkbox"
class="sr-only"
name="platform"
checked=""
value="web"
/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-6"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>
<span class="label">Web</span>
</label>
<label
class="relative flex flex-col items-center gap-3 p-4 border rounded-lg cursor-pointer has-checked:border-primary has-checked:bg-primary/[2.5%]"
>
<input type="checkbox" class="sr-only" name="platform" value="mobile" />
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-6"><rect width="14" height="20" x="5" y="2" rx="2" ry="2"/><path d="M12 18h.01"/></svg>
<span class="label">Mobile</span>
</label>
<label
class="relative flex flex-col items-center gap-3 p-4 border rounded-lg cursor-pointer has-checked:border-primary has-checked:bg-primary/[2.5%]"
>
<input type="checkbox" class="sr-only" name="platform" value="api" />
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-6"><path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/></svg>
<span class="label">API</span>
</label>
</div>
</div>
</div>List select
Use checkboxes inside list items for a multi-select list with descriptions.
<div class="w-full max-w-md">
<div class="grid gap-3">
<span class="label">Features</span>
<div class="grid gap-3">
<label
class="relative flex items-start justify-between gap-3 p-4 border rounded-lg cursor-pointer has-checked:border-primary has-checked:bg-primary/[2.5%]"
>
<div class="flex-1 grid gap-2">
<div class="label">Cloud storage</div>
<div class="text-sm text-muted-foreground">
50 GB of secure cloud storage
</div>
</div>
<input
type="checkbox"
class="checkbox"
name="features"
checked=""
value="storage"
/>
</label>
<label
class="relative flex items-start justify-between gap-3 p-4 border rounded-lg cursor-pointer has-checked:border-primary has-checked:bg-primary/[2.5%]"
>
<div class="flex-1 grid gap-2">
<div class="label">Automatic backups</div>
<div class="text-sm text-muted-foreground">
Daily backups with 30-day retention
</div>
</div>
<input
type="checkbox"
class="checkbox"
name="features"
value="backup"
/>
</label>
<label
class="relative flex items-start justify-between gap-3 p-4 border rounded-lg cursor-pointer has-checked:border-primary has-checked:bg-primary/[2.5%]"
>
<div class="flex-1 grid gap-2">
<div class="label">Priority support</div>
<div class="text-sm text-muted-foreground">
24/7 dedicated support team
</div>
</div>
<input
type="checkbox"
class="checkbox"
name="features"
value="support"
/>
</label>
</div>
</div>
</div>Toggle all
Mark one checkbox with data-sp-toggle-all to make it a master that controls every other checkbox in the same form. Toggling the master flips all targets. Toggling individual targets updates the master to checked, unchecked, or a "some selected" mixed state automatically.
Targets are grouped to the master by the standard HTML form attribute. If the master has form="my-form", every checkbox with the same form="my-form" is a target. Otherwise, every checkbox sharing the same closest <form> ancestor is a target. Disabled targets are skipped.
<form id="toggle-all-form">
<div class="field-group">
<div class="field field-horizontal">
<input type="checkbox" class="checkbox" id="toggle-all-master" data-sp-toggle-all />
<label class="label" for="toggle-all-master">Select all</label>
</div>
<div class="field-group gap-3 pl-6">
<div class="field field-horizontal">
<input type="checkbox" class="checkbox" id="toggle-all-1" name="ids[]" value="1" />
<label class="label" for="toggle-all-1">One</label>
</div>
<div class="field field-horizontal">
<input type="checkbox" class="checkbox" id="toggle-all-2" name="ids[]" value="2" />
<label class="label" for="toggle-all-2">Two</label>
</div>
<div class="field field-horizontal">
<input type="checkbox" class="checkbox" id="toggle-all-3" name="ids[]" value="3" />
<label class="label" for="toggle-all-3">Three</label>
</div>
</div>
</div>
</form>The master and its targets do not need to be inside the same DOM container. Use the form="X" attribute on both so they can live anywhere.
<input type="checkbox" form="my-form" data-sp-toggle-all />
...
<input type="checkbox" form="my-form" name="ids[]" value="1" />Don't give the master a name attribute. Inputs without a name are excluded from form submission, which is what you want here — the master is a UI controller, not a value to submit.
Pre-checked state
If targets are pre-checked on render (for example, from server-rendered state), set the master's data-sp-toggle-all value to match. This lets the CSS show the right icon at first paint without waiting for JS.
| Value | Meaning |
|---|---|
data-sp-toggle-all="none" | No targets checked (default) |
data-sp-toggle-all="some" | Some targets checked (dash icon) |
data-sp-toggle-all="all" | All targets checked (checkmark) |
<!-- Some targets pre-checked: dash paints immediately -->
<input type="checkbox" class="checkbox" data-sp-toggle-all="some" />
<!-- All targets pre-checked: checkmark paints immediately, master is also `checked` -->
<input type="checkbox" class="checkbox" data-sp-toggle-all="all" checked />For the default "none" state you can omit the value entirely — bare data-sp-toggle-all and data-sp-toggle-all="" render the same as data-sp-toggle-all="none". The JavaScript normalizes to "none" after the first sync.
The JavaScript keeps the attribute in sync after every change, so the value is only set explicitly on the server side; later toggles in the browser are handled automatically.
How it works
The checkbox component is a CSS-only utility class applied to a native <input type="checkbox"> element.
Structure
Use the .checkbox class on an <input type="checkbox">. Pair it with a .label element connected via for and id:
<input type="checkbox" class="checkbox" id="terms" />
<label class="label" for="terms">Accept terms</label>Disabled state
Add disabled to the checkbox. Use peer on the checkbox so the label automatically dims via peer-disabled:
<input type="checkbox" class="checkbox peer" id="cb" disabled />
<label class="label" for="cb">Disabled</label>Validation
Add aria-invalid="true" to show the checkbox in an error state:
<input type="checkbox" class="checkbox" aria-invalid="true" />Class reference
| Class | Description |
|---|---|
checkbox | Base checkbox styles |
Data attributes
| Attribute | Element | Description |
|---|---|---|
data-sp-toggle-all | Master checkbox | Identifies a checkbox as a master controlling other checkboxes in the same form. The value mirrors the current group state: none / some / all. Servers can pre-render some or all to avoid a JS-driven flicker on first paint. |