Checkbox
Single and grouped checkboxes across all sizes, states, and layout patterns — including indeterminate, list groups, and description text.
Sizes
DaisyUI ships checkbox-xs through checkbox-lg.
Use checkbox-sm as the default in dense forms; checkbox-md
for touch-friendly targets.
<input type="checkbox" class="checkbox checkbox-xs" />
<input type="checkbox" class="checkbox checkbox-sm" />
<input type="checkbox" class="checkbox checkbox-md" />
<input type="checkbox" class="checkbox checkbox-lg" />
States
Default, checked, indeterminate (set via JS property, not HTML attribute), and disabled variants. The indeterminate state is the only one that requires JS — it cannot be expressed in markup alone.
<!-- Unchecked / checked via HTML attribute -->
<input type="checkbox" class="checkbox checkbox-sm" />
<input type="checkbox" class="checkbox checkbox-sm" checked />
<!-- Indeterminate — must be set via JS, not HTML -->
<input type="checkbox" class="checkbox checkbox-sm" id="chk-indeterminate" />
<script>
document.getElementById('chk-indeterminate').indeterminate = true;
</script>
<!-- Disabled states -->
<input type="checkbox" class="checkbox checkbox-sm" disabled />
<input type="checkbox" class="checkbox checkbox-sm" checked disabled />
Color variants
DaisyUI semantic color modifiers. Use checkbox-primary as the default
brand color; reserve checkbox-error for validation feedback only.
<input type="checkbox" class="checkbox checkbox-sm" checked />
<input type="checkbox" class="checkbox checkbox-sm checkbox-primary" checked />
<input type="checkbox" class="checkbox checkbox-sm checkbox-secondary" checked />
<input type="checkbox" class="checkbox checkbox-sm checkbox-accent" checked />
<input type="checkbox" class="checkbox checkbox-sm checkbox-success" checked />
<input type="checkbox" class="checkbox checkbox-sm checkbox-warning" checked />
<input type="checkbox" class="checkbox checkbox-sm checkbox-error" checked />
<input type="checkbox" class="checkbox checkbox-sm checkbox-info" checked />
With description text
Pair each checkbox with a secondary line of helper text for settings or permission panels where the label alone isn't self-explanatory.
<label class="flex gap-3 cursor-pointer items-start" for="chk-email">
<input type="checkbox" id="chk-email"
class="checkbox checkbox-sm checkbox-primary mt-0.5 shrink-0"
checked />
<div>
<div class="text-sm font-medium leading-tight">Email notifications</div>
<div class="text-xs text-base-content/50 mt-0.5">
Receive updates about your account activity.
</div>
</div>
</label>
List group with Select all
A parent "Select all" checkbox drives all children via Alpine.js. When children are partially checked the parent enters indeterminate state automatically — no extra CSS needed, pure DOM property.
of selected
<div x-data="{
items: [
{ id: 1, label: 'Read access', checked: true },
{ id: 2, label: 'Write access', checked: false },
{ id: 3, label: 'Delete access', checked: false },
{ id: 4, label: 'Admin access', checked: true },
],
get allChecked() { return this.items.every(i => i.checked); },
get someChecked() { return this.items.some(i => i.checked) && !this.allChecked; },
toggleAll(e) { this.items.forEach(i => i.checked = e.target.checked); },
}"
x-init="
$watch('someChecked', v => { $refs.parentChk.indeterminate = v; });
$refs.parentChk.indeterminate = someChecked;
">
<!-- Parent -->
<label class="flex items-center gap-3 cursor-pointer">
<input type="checkbox" class="checkbox checkbox-sm checkbox-primary"
x-ref="parentChk" :checked="allChecked" @change="toggleAll($event)" />
<span class="text-sm font-semibold">Select all</span>
</label>
<!-- Children -->
<template x-for="item in items" :key="item.id">
<label class="flex items-center gap-3 cursor-pointer">
<input type="checkbox" class="checkbox checkbox-sm checkbox-primary"
x-model="item.checked" />
<span class="text-sm" x-text="item.label"></span>
</label>
</template>
</div>
Bordered card list
Each option is a full-width card. Clicking anywhere on the card toggles the checkbox. The selected card gets a highlighted border via Alpine-driven conditional classes — no JS outside of Alpine required.
<label
class="flex items-center gap-4 p-4 rounded-[--radius-sm] border cursor-pointer transition-colors"
:class="plan.checked
? 'border-primary bg-primary/5'
: 'border-base-200 hover:border-base-300 bg-base-100'"
>
<input type="checkbox" class="checkbox checkbox-sm checkbox-primary shrink-0"
x-model="plan.checked" />
<div class="flex-1 min-w-0">
<div class="flex items-baseline justify-between gap-2">
<span class="text-sm font-semibold" x-text="plan.name"></span>
<span class="text-sm font-medium text-primary" x-text="plan.price"></span>
</div>
<div class="text-xs text-base-content/50 mt-0.5" x-text="plan.features"></div>
</div>
</label>
Switch appearance
DaisyUI's toggle class renders a checkbox as a sliding toggle switch —
same semantics, different affordance. Prefer toggles for binary on/off settings;
prefer checkboxes for multi-select lists.
<!-- Toggle is a checkbox with class="toggle" instead of "checkbox" -->
<label class="flex items-center justify-between gap-4 cursor-pointer">
<div>
<div class="text-sm font-medium">Dark mode</div>
</div>
<input type="checkbox" class="toggle toggle-sm toggle-primary" checked />
</label>
<!-- With description -->
<label class="flex items-center justify-between gap-4 cursor-pointer">
<div>
<div class="text-sm font-medium">Auto-save drafts</div>
<div class="text-xs text-base-content/50">Saves every 30 seconds.</div>
</div>
<input type="checkbox" class="toggle toggle-sm toggle-success" checked />
</label>
Validation state
Required checkboxes (e.g. terms acceptance) with inline error feedback. Alpine toggles the error message based on whether the box is checked on submit.
You must accept the terms to continue.
✓ Form submitted successfully.
<div x-data="{ accepted: false, submitted: false,
get invalid() { return this.submitted && !this.accepted; } }">
<label class="flex items-start gap-3 cursor-pointer">
<input type="checkbox"
class="checkbox checkbox-sm mt-0.5 shrink-0"
:class="invalid ? 'checkbox-error' : 'checkbox-primary'"
x-model="accepted" />
<span class="text-sm">I agree to the <a href="#" class="link link-primary">Terms</a>.</span>
</label>
<p class="text-xs text-error mt-1.5 ml-6" x-show="invalid" x-cloak>
You must accept the terms to continue.
</p>
<button class="btn btn-primary btn-sm mt-4" @click="submitted = true">
Submit
</button>
</div>