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.

Dietary requirements
<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.

Notifications

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.

Platform
<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.

Features
<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.

ValueMeaning
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

ClassDescription
checkboxBase checkbox styles

Data attributes

AttributeElementDescription
data-sp-toggle-allMaster checkboxIdentifies 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.