SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/tailwind-checkboxes

6 Tailwind Checkboxes

5 Tailwind1 with JSPublished 2026-10-04Free · no sign-up

Six checkbox patterns in Tailwind: a custom box with an SVG tick, selectable cards, a to-do list that strikes out finished items, filter chips, a required terms checkbox with an error and a select-all control with an indeterminate state.

01. Tailwind Custom Checkbox

TailwindForm

A custom checkbox using appearance-none on the real input plus an SVG tick placed over it with peer-checked:block. The input keeps its keyboard and form behaviour, and focus-visible:ring classes give keyboard users a clear outline.

View code
<div class="grid gap-3 text-[15px] text-slate-800">
  <label class="flex cursor-pointer items-center gap-3">
    <span class="relative grid">
      <input type="checkbox" class="peer h-5 w-5 appearance-none rounded-md border-2 border-slate-400 bg-white checked:border-blue-600 checked:bg-blue-600 focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-blue-200" checked>
      <svg class="pointer-events-none absolute inset-0 m-auto hidden h-3.5 w-3.5 text-white peer-checked:block" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 8.5l3 3 7-7" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
    </span>
    Keep me signed in
  </label>
  <label class="flex cursor-pointer items-center gap-3">
    <span class="relative grid">
      <input type="checkbox" class="peer h-5 w-5 appearance-none rounded-md border-2 border-slate-400 bg-white checked:border-blue-600 checked:bg-blue-600 focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-blue-200">
      <svg class="pointer-events-none absolute inset-0 m-auto hidden h-3.5 w-3.5 text-white peer-checked:block" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 8.5l3 3 7-7" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
    </span>
    Email me about new arrivals
  </label>
</div>

02. Tailwind Checkbox Cards

TailwindCards

Multi-select cards where the entire card is the label. has-[:checked]: on the label changes the border and background when its checkbox is ticked, and has-[:focus-visible]: adds the ring, so the card behaves like one large accessible checkbox.

View code
<fieldset class="grid w-full max-w-xl grid-cols-1 gap-3 sm:grid-cols-3">
  <legend class="mb-3 text-xs font-bold uppercase tracking-widest text-slate-400">Integrations</legend>
  <label class="relative grid cursor-pointer gap-1 rounded-2xl border border-slate-700 bg-slate-900 p-4 text-slate-100 has-[:checked]:border-sky-400 has-[:checked]:bg-sky-950 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-sky-300"><input type="checkbox" class="absolute right-3 top-3 h-4 w-4 accent-sky-400" checked><b>Email</b><span class="text-sm text-slate-400">Send receipts</span></label>
  <label class="relative grid cursor-pointer gap-1 rounded-2xl border border-slate-700 bg-slate-900 p-4 text-slate-100 has-[:checked]:border-sky-400 has-[:checked]:bg-sky-950 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-sky-300"><input type="checkbox" class="absolute right-3 top-3 h-4 w-4 accent-sky-400"><b>SMS</b><span class="text-sm text-slate-400">Delivery texts</span></label>
  <label class="relative grid cursor-pointer gap-1 rounded-2xl border border-slate-700 bg-slate-900 p-4 text-slate-100 has-[:checked]:border-sky-400 has-[:checked]:bg-sky-950 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-sky-300"><input type="checkbox" class="absolute right-3 top-3 h-4 w-4 accent-sky-400" checked><b>Slack</b><span class="text-sm text-slate-400">Team alerts</span></label>
</fieldset>

03. Tailwind To-Do Checklist

TailwindList

A checklist where ticking an item strikes it through and greys it out, using peer-checked:line-through on the text that follows each checkbox. accent-color sets the native tick colour in one utility while keeping the browser's built-in checkbox.

View code
<ul class="w-full max-w-sm divide-y divide-slate-100 rounded-2xl bg-white px-5 shadow-lg shadow-slate-900/10">
  <li class="py-3"><label class="flex cursor-pointer items-center gap-3"><input type="checkbox" class="peer h-4 w-4 accent-teal-600" checked><span class="text-slate-900 peer-checked:text-slate-400 peer-checked:line-through">Photograph new stock</span></label></li>
  <li class="py-3"><label class="flex cursor-pointer items-center gap-3"><input type="checkbox" class="peer h-4 w-4 accent-teal-600"><span class="text-slate-900 peer-checked:text-slate-400 peer-checked:line-through">Write product titles</span></label></li>
  <li class="py-3"><label class="flex cursor-pointer items-center gap-3"><input type="checkbox" class="peer h-4 w-4 accent-teal-600"><span class="text-slate-900 peer-checked:text-slate-400 peer-checked:line-through">Publish to the store</span></label></li>
</ul>

04. Tailwind Filter Chips

TailwindFilter

Checkbox chips for filtering a product grid. The input is sr-only and the visible chip is the label, styled through has-[:checked]: so selected chips fill with colour and show a tick from a before: pseudo-element.

View code
<fieldset class="flex max-w-md flex-wrap gap-2 text-sm font-semibold">
  <legend class="mb-3 w-full text-slate-400">Colour</legend>
  <label class="cursor-pointer rounded-full border border-slate-600 px-4 py-2 text-slate-200 has-[:checked]:border-rose-400 has-[:checked]:bg-rose-500/20 has-[:checked]:text-white has-[:checked]:before:content-['\2713_'] has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-rose-300"><input type="checkbox" class="sr-only" checked>Red</label>
  <label class="cursor-pointer rounded-full border border-slate-600 px-4 py-2 text-slate-200 has-[:checked]:border-rose-400 has-[:checked]:bg-rose-500/20 has-[:checked]:text-white has-[:checked]:before:content-['\2713_'] has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-rose-300"><input type="checkbox" class="sr-only">Blue</label>
  <label class="cursor-pointer rounded-full border border-slate-600 px-4 py-2 text-slate-200 has-[:checked]:border-rose-400 has-[:checked]:bg-rose-500/20 has-[:checked]:text-white has-[:checked]:before:content-['\2713_'] has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-rose-300"><input type="checkbox" class="sr-only" checked>Green</label>
  <label class="cursor-pointer rounded-full border border-slate-600 px-4 py-2 text-slate-200 has-[:checked]:border-rose-400 has-[:checked]:bg-rose-500/20 has-[:checked]:text-white has-[:checked]:before:content-['\2713_'] has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-rose-300"><input type="checkbox" class="sr-only">Black</label>
</fieldset>

05. Tailwind Required Terms Checkbox

TailwindValidation

A required agreement checkbox with an error that appears only after a submit attempt. Tailwind's user-invalid: variant styles the checkbox and its label red, and group-has-[:user-invalid]: reveals the message tied to the input with aria-describedby.

View code
<form class="group grid w-full max-w-sm gap-3 rounded-2xl bg-white p-5 shadow-lg shadow-slate-900/10" onsubmit="event.preventDefault()">
  <label class="flex cursor-pointer items-center gap-3 text-slate-800 group-has-[:user-invalid]:text-red-700">
    <input type="checkbox" required aria-describedby="tw-terr" class="h-4 w-4 accent-blue-600"> I agree to the terms
  </label>
  <p id="tw-terr" class="hidden text-sm text-red-700 group-has-[:user-invalid]:block">Please accept the terms to continue.</p>
  <button class="justify-self-start rounded-lg bg-slate-900 px-4 py-2.5 text-sm font-bold text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600">Create account</button>
</form>

06. Tailwind Select All Checkbox

TailwindJavaScript

A table-style select-all checkbox that shows a dash when only some rows are selected. A short script sets indeterminate, which only JavaScript can do, and Tailwind's indeterminate: variant gives that state its own colour.

View code
<div class="w-full max-w-sm rounded-2xl border border-slate-700 bg-slate-900 p-4 text-slate-200">
  <label class="flex items-center gap-3 border-b border-slate-700 pb-3 font-semibold"><input id="tw-all" type="checkbox" class="h-4 w-4 accent-indigo-400 indeterminate:accent-amber-400"> Select all orders</label>
  <label class="mt-3 flex items-center gap-3"><input type="checkbox" class="tw-row h-4 w-4 accent-indigo-400" checked> #1042, Lagos</label>
  <label class="mt-2 flex items-center gap-3"><input type="checkbox" class="tw-row h-4 w-4 accent-indigo-400"> #1043, Leeds</label>
  <label class="mt-2 flex items-center gap-3"><input type="checkbox" class="tw-row h-4 w-4 accent-indigo-400" checked> #1044, Lahore</label>
</div>
const all = document.getElementById('tw-all'), rows = [...document.querySelectorAll('.tw-row')];
function sync() { const n = rows.filter(r => r.checked).length; all.checked = n === rows.length; all.indeterminate = n > 0 && n < rows.length; }
all.addEventListener('change', () => { rows.forEach(r => r.checked = all.checked); sync(); });
rows.forEach(r => r.addEventListener('change', sync));
sync();

About these Tailwind Checkboxes

Custom box with appearance-none

Add appearance-none to the input and style it with border, background and checked: utilities. An SVG tick placed after it shows with peer-checked:block, while the real input keeps keyboard and form behaviour.

Labels that react with has-[]

has-[:checked]: on a label styles it when the checkbox inside is ticked, which is how the cards and chips change border and background. Add has-[:focus-visible]:ring-2 so the whole card shows focus.

Native ticks with accent colour

For simple lists, accent-teal-600 recolours the browser's own checkbox in one class, which keeps platform conventions and high-contrast mode support.

Errors after interaction

The terms demo uses group-has-[:user-invalid]: so the error only appears after someone has tried to submit, not as soon as the page loads.

Frequently asked questions

Do these work in Tailwind v4?

Yes. They use variants available in v3.4 and v4.

Which demo uses JavaScript?

Only select all, because the indeterminate state must be set with JavaScript.

How do I make the cards stack on phones?

They already do: the grid is one column by default and three from the sm breakpoint.