Open demo

CSS code

HTML
<div><span class="lbl">Square tick</span><div class="row">
<label class="cb"><input type="checkbox" checked><span class="bx"></span>Remember me</label>
<label class="cb"><input type="checkbox"><span class="bx"></span>Subscribe</label></div></div>
<div><span class="lbl">Circular tick</span><div class="row">
<label class="cb round"><input type="checkbox" checked><span class="bx"></span>Accepted</label>
<label class="cb round"><input type="checkbox"><span class="bx"></span>Pending</label></div></div>
<div><span class="lbl">Dash state</span><div class="row">
<label class="cb dash"><input type="checkbox" checked><span class="bx"></span>Partial selection</label></div></div>
<div><span class="lbl">Whole row is the target</span><div class="row">
<label class="rowt"><span><strong>Two-factor auth</strong><small>Ask for a code at sign-in</small></span>
<input type="checkbox" checked><span class="bx"></span></label>
<label class="rowt"><span><strong>Marketing email</strong><small>Product news, roughly monthly</small></span>
<input type="checkbox"><span class="bx"></span></label></div></div>
CSS
/* Checkbox toggles: a visually hidden checkbox followed by a .bx box that draws the tick. */
.cb input,.rowt input{position:absolute;opacity:0;width:0;height:0;margin:0}
.cb{display:inline-flex;align-items:center;gap:11px;cursor:pointer;font-size:.9rem}
.bx{box-sizing:border-box;flex-shrink:0;width:22px;height:22px;border:2px solid #7c8aa0;border-radius:6px;position:relative;
  transition:background .18s,border-color .18s}
.bx::after{content:"";position:absolute;top:3px;left:7px;width:5px;height:10px;border:solid #fff;
  border-width:0 2px 2px 0;transform:rotate(45deg) scale(0);transition:transform .18s}
.cb input:checked+.bx{background:#2563eb;border-color:#2563eb}
.cb input:checked+.bx::after,.rowt input:checked~.bx::after{transform:rotate(45deg) scale(1)}
.cb input:focus-visible+.bx,.rowt input:focus-visible~.bx{outline:2px solid #2563eb;outline-offset:2px}
.cb.round .bx{border-radius:50%}
.cb.dash .bx::after{top:9px;left:4px;width:10px;height:0;border-width:0 0 2px 0;transform:scaleX(0)}
.cb.dash input:checked+.bx::after{transform:scaleX(1)}
/* the whole row is the target */
.rowt{box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:20px;width:100%;max-width:420px;
  padding:13px 16px;border:1px solid #e2e8f0;border-radius:11px;cursor:pointer;background:#fff;
  transition:border-color .18s,background .18s}
.rowt:hover{background:#f8fafc}
.rowt input:checked~.bx{background:#16a34a;border-color:#16a34a}
.rowt small{display:block;color:#64748b;font-size:.78rem;margin-top:2px}
@media (prefers-reduced-motion:reduce){.bx,.bx::after,.rowt{transition:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Square tick</span><div class="demo-row">
<div class="form-check cbx"><input class="form-check-input" type="checkbox" id="cb-remember" checked><label class="form-check-label" for="cb-remember">Remember me</label></div>
<div class="form-check cbx"><input class="form-check-input" type="checkbox" id="cb-subscribe"><label class="form-check-label" for="cb-subscribe">Subscribe</label></div></div></div>
<div><span class="lbl">Circular tick</span><div class="demo-row">
<div class="form-check cbx"><input class="form-check-input rounded-circle" type="checkbox" id="cb-accepted" checked><label class="form-check-label" for="cb-accepted">Accepted</label></div>
<div class="form-check cbx"><input class="form-check-input rounded-circle" type="checkbox" id="cb-pending"><label class="form-check-label" for="cb-pending">Pending</label></div></div></div>
<div><span class="lbl">Dash state</span><div class="demo-row">
<div class="form-check cbx dash"><input class="form-check-input" type="checkbox" id="cb-partial" checked><label class="form-check-label" for="cb-partial">Partial selection</label></div></div></div>
<div><span class="lbl">Whole row is the target</span><div class="demo-row">
<div class="list-group rowt"><label class="list-group-item list-group-item-action d-flex align-items-center justify-content-between"><span><strong>Two-factor auth</strong><small>Ask for a code at sign-in</small></span>
<input class="form-check-input" type="checkbox" checked></label></div>
<div class="list-group rowt"><label class="list-group-item list-group-item-action d-flex align-items-center justify-content-between"><span><strong>Marketing email</strong><small>Product news, roughly monthly</small></span>
<input class="form-check-input" type="checkbox"></label></div></div></div>
CSS
/* Bootstrap .form-check-input, resized and recoloured. The tick is Bootstrap's --bs-form-check-bg-image. */
.cbx{--cb-border:#7c8aa0;--cb-on:#2563eb;--cb-focus:#2563eb;
  display:inline-flex;align-items:center;gap:11px;min-height:0;margin:0;padding:0;font-size:.9rem}
.cbx .form-check-input,.rowt .form-check-input{width:22px;height:22px;margin:0;float:none;flex-shrink:0;cursor:pointer;
  border:2px solid var(--cb-border);border-radius:6px;transition:background-color .18s,border-color .18s}
.cbx .form-check-label{cursor:pointer}
.cbx .form-check-input:focus,.rowt .form-check-input:focus{box-shadow:none;border-color:var(--cb-border)}
.cbx .form-check-input:focus-visible,.rowt .form-check-input:focus-visible{outline:2px solid var(--cb-focus);outline-offset:2px}
.cbx .form-check-input:checked{background-color:var(--cb-on);border-color:var(--cb-on)}
.cbx .form-check-input:checked,.rowt .form-check-input:checked{background-size:18px;
  --bs-form-check-bg-image:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'><path d='M4.5 10.1l4.2 4.2 7.8-7.8' fill='none' stroke='%23fff' stroke-width='2'/></svg>")}
.cbx.dash .form-check-input:checked{
  --bs-form-check-bg-image:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'><path d='M4 10h10' fill='none' stroke='%23fff' stroke-width='2'/></svg>")}
/* the whole row is the target: a Bootstrap .list-group-item label */
.rowt{--cb-border:#7c8aa0;--cb-focus:#2563eb;
  --bs-list-group-border-color:#e2e8f0;--bs-list-group-border-radius:11px;--bs-list-group-item-padding-x:16px;
  --bs-list-group-item-padding-y:13px;--bs-list-group-action-hover-bg:#f8fafc;--bs-list-group-action-color:#1e293b;--bs-list-group-action-hover-color:#1e293b;--bs-list-group-action-active-color:#1e293b;--bs-list-group-action-active-bg:#f1f5f9;
  --bs-list-group-color:#1e293b;--bs-list-group-bg:#fff;width:100%;max-width:420px}
.rowt .list-group-item{gap:20px;cursor:pointer}
.rowt .form-check-input:checked{background-color:#16a34a;border-color:#16a34a}
.rowt small{display:block;color:#64748b;font-size:.78rem;margin-top:2px}
@media (prefers-reduced-motion:reduce){.cbx .form-check-input,.rowt .form-check-input,.rowt .list-group-item{transition:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#64748b] uppercase">Square tick</span><div class="flex flex-wrap items-center gap-[18px]">
<label class="inline-flex cursor-pointer items-center gap-[11px] text-[.9rem]"><input type="checkbox" class="peer sr-only" checked><span class="relative size-[22px] shrink-0 rounded-md border-2 border-cb-border transition-[background-color,border-color,color] duration-[180ms] peer-checked:border-cb-on peer-checked:bg-cb-on peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-cb-on after:absolute after:top-[3px] after:left-[7px] after:h-3 after:w-[7px] after:scale-0 after:rotate-45 after:border-r-2 after:border-b-2 after:border-white after:transition-transform after:duration-[180ms] peer-checked:after:scale-100 motion-reduce:transition-none motion-reduce:after:transition-none"></span>Remember me</label>
<label class="inline-flex cursor-pointer items-center gap-[11px] text-[.9rem]"><input type="checkbox" class="peer sr-only"><span class="relative size-[22px] shrink-0 rounded-md border-2 border-cb-border transition-[background-color,border-color,color] duration-[180ms] peer-checked:border-cb-on peer-checked:bg-cb-on peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-cb-on after:absolute after:top-[3px] after:left-[7px] after:h-3 after:w-[7px] after:scale-0 after:rotate-45 after:border-r-2 after:border-b-2 after:border-white after:transition-transform after:duration-[180ms] peer-checked:after:scale-100 motion-reduce:transition-none motion-reduce:after:transition-none"></span>Subscribe</label></div></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#64748b] uppercase">Circular tick</span><div class="flex flex-wrap items-center gap-[18px]">
<label class="inline-flex cursor-pointer items-center gap-[11px] text-[.9rem]"><input type="checkbox" class="peer sr-only" checked><span class="relative size-[22px] shrink-0 rounded-full border-2 border-cb-border transition-[background-color,border-color,color] duration-[180ms] peer-checked:border-cb-on peer-checked:bg-cb-on peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-cb-on after:absolute after:top-[3px] after:left-[7px] after:h-3 after:w-[7px] after:scale-0 after:rotate-45 after:border-r-2 after:border-b-2 after:border-white after:transition-transform after:duration-[180ms] peer-checked:after:scale-100 motion-reduce:transition-none motion-reduce:after:transition-none"></span>Accepted</label>
<label class="inline-flex cursor-pointer items-center gap-[11px] text-[.9rem]"><input type="checkbox" class="peer sr-only"><span class="relative size-[22px] shrink-0 rounded-full border-2 border-cb-border transition-[background-color,border-color,color] duration-[180ms] peer-checked:border-cb-on peer-checked:bg-cb-on peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-cb-on after:absolute after:top-[3px] after:left-[7px] after:h-3 after:w-[7px] after:scale-0 after:rotate-45 after:border-r-2 after:border-b-2 after:border-white after:transition-transform after:duration-[180ms] peer-checked:after:scale-100 motion-reduce:transition-none motion-reduce:after:transition-none"></span>Pending</label></div></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#64748b] uppercase">Dash state</span><div class="flex flex-wrap items-center gap-[18px]">
<label class="inline-flex cursor-pointer items-center gap-[11px] text-[.9rem]"><input type="checkbox" class="peer sr-only" checked><span class="relative size-[22px] shrink-0 rounded-md border-2 border-cb-border transition-[background-color,border-color,color] duration-[180ms] peer-checked:border-cb-on peer-checked:bg-cb-on peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-cb-on after:absolute after:top-[9px] after:left-1 after:h-[2px] after:w-[10px] after:scale-x-0 after:border-b-2 after:border-white after:transition-transform after:duration-[180ms] peer-checked:after:scale-x-100 motion-reduce:transition-none motion-reduce:after:transition-none"></span>Partial selection</label></div></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#64748b] uppercase">Whole row is the target</span><div class="flex flex-wrap items-center gap-[18px]">
<label class="flex w-full max-w-[420px] cursor-pointer items-center justify-between gap-5 rounded-[11px] border border-[#e2e8f0] bg-white px-4 py-[13px] transition-colors duration-[180ms] hover:bg-[#f8fafc] motion-reduce:transition-none"><span><strong>Two-factor auth</strong><small class="mt-0.5 block text-[.78rem] text-[#64748b]">Ask for a code at sign-in</small></span>
<input type="checkbox" class="peer sr-only" checked><span class="relative size-[22px] shrink-0 rounded-md border-2 border-cb-border transition-[background-color,border-color,color] duration-[180ms] peer-checked:border-cb-ok peer-checked:bg-cb-ok peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-cb-on after:absolute after:top-[3px] after:left-[7px] after:h-3 after:w-[7px] after:scale-0 after:rotate-45 after:border-r-2 after:border-b-2 after:border-white after:transition-transform after:duration-[180ms] peer-checked:after:scale-100 motion-reduce:transition-none motion-reduce:after:transition-none"></span></label>
<label class="flex w-full max-w-[420px] cursor-pointer items-center justify-between gap-5 rounded-[11px] border border-[#e2e8f0] bg-white px-4 py-[13px] transition-colors duration-[180ms] hover:bg-[#f8fafc] motion-reduce:transition-none"><span><strong>Marketing email</strong><small class="mt-0.5 block text-[.78rem] text-[#64748b]">Product news, roughly monthly</small></span>
<input type="checkbox" class="peer sr-only"><span class="relative size-[22px] shrink-0 rounded-md border-2 border-cb-border transition-[background-color,border-color,color] duration-[180ms] peer-checked:border-cb-ok peer-checked:bg-cb-ok peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-cb-on after:absolute after:top-[3px] after:left-[7px] after:h-3 after:w-[7px] after:scale-0 after:rotate-45 after:border-r-2 after:border-b-2 after:border-white after:transition-transform after:duration-[180ms] peer-checked:after:scale-100 motion-reduce:transition-none motion-reduce:after:transition-none"></span></label></div></div>
CSS
@theme {
  --color-cb-border: #7c8aa0;
  --color-cb-on: #2563eb;
  --color-cb-ok: #16a34a;
}

About this set

Custom checkboxes for settings pages and forms, in four variants. Square tick is a 22 pixel rounded box that fills blue and draws a white tick when checked. Circular tick is the same control with a round box, suited to accept or status lists. Dash state shows a horizontal bar instead of a tick, the look people expect for a partial selection such as a select-all header. Whole row is the target turns a full settings row, with a bold title and a grey description, into one large click target with the box on the right, which is easier to hit on touch screens. Each variant keeps a real checkbox in the markup, visually hidden, so labels, keyboard use and form submission behave natively; the visible box is a sibling span styled with :checked. The Bootstrap version uses .form-check-input and a .list-group-item label for the row, and the Tailwind version uses peer-checked utilities on the same structure.

What’s included

  • Square, circular, dash and full-row variants
  • Tick and dash scale in when checked (SVG images in the Bootstrap version)
  • Full-row label for large touch targets
  • Box border darkened to #7c8aa0 so the unchecked box reaches 3:1
  • Bootstrap version built on .form-check and .list-group

Accessibility

Every checkbox is named by its visible label text, including the full-row variant where the title and description form the name. Tab moves between boxes and Space checks them. Focus draws a 2px blue outline around the visible box, and the fill and tick animations are removed under prefers-reduced-motion. The dash variant is styled only; set the indeterminate property from script if you need that state announced.

Customise it

Change the border and fill colours on .bx and .cb input:checked+.bx (plain CSS), --cb-border and --cb-on on .cbx plus the --bs-list-group-* variables on .rowt (Bootstrap), or the --color-cb-* theme colours (Tailwind). The box size is the 22px width and height.