Open demo

CSS code

HTML
<div><span class="lbl">Popover checklist with a live count</span><div class="card">
<form class="mx" action="#">
  <span class="mx-label" id="mx-top-label">Extra toppings</span>
  <div class="mx-wrap">
    <button type="button" class="mx-trigger" popovertarget="mx-top" aria-labelledby="mx-top-label">
      <span class="mx-none">None yet</span><span class="mx-some">selected</span>
      <svg class="mx-chev" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m4 6 4 4 4-4"/></svg>
    </button>
    <div class="mx-pop" id="mx-top" popover>
      <fieldset class="mx-set">
        <legend class="sr-only">Extra toppings</legend>
        <label class="mx-opt"><input type="checkbox" name="toppings" value="mozzarella" checked> Buffalo mozzarella <span class="mx-price">+€2.00</span></label>
        <label class="mx-opt"><input type="checkbox" name="toppings" value="basil" checked> Fresh basil <span class="mx-price">+€0.50</span></label>
        <label class="mx-opt"><input type="checkbox" name="toppings" value="mushrooms"> Roasted mushrooms <span class="mx-price">+€1.50</span></label>
        <label class="mx-opt"><input type="checkbox" name="toppings" value="olives"> Kalamata olives <span class="mx-price">+€1.00</span></label>
        <label class="mx-opt"><input type="checkbox" name="toppings" value="nduja" checked> Spicy nduja <span class="mx-price">+€2.50</span></label>
        <label class="mx-opt"><input type="checkbox" name="toppings" value="peppers"> Roasted peppers <span class="mx-price">+€1.20</span></label>
        <label class="mx-opt"><input type="checkbox" name="toppings" value="anchovies"> Anchovies <span class="mx-price">+€1.80</span></label>
        <label class="mx-opt"><input type="checkbox" name="toppings" value="rocket"> Wild rocket <span class="mx-price">+€0.80</span></label>
      </fieldset>
      <div class="mx-foot">
        <span class="mx-total" aria-hidden="true"></span>
        <button type="reset" class="mx-btn ghost">Reset</button>
        <button type="button" class="mx-btn solid" popovertarget="mx-top" popovertargetaction="hide">Done</button>
      </div>
    </div>
    <span class="mx-count" aria-hidden="true"></span>
  </div>
</form>
</div></div>

<div><span class="lbl">Checkbox chips with a live count</span><div class="card">
<form class="mx" action="#">
  <fieldset class="mx-chips">
    <legend class="mx-label">Cuisine</legend>
    <div class="mx-chiplist">
      <label class="mx-chip"><input type="checkbox" name="cuisine" value="italian"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Italian</label>
      <label class="mx-chip"><input type="checkbox" name="cuisine" value="japanese" checked><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Japanese</label>
      <label class="mx-chip"><input type="checkbox" name="cuisine" value="mexican"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Mexican</label>
      <label class="mx-chip"><input type="checkbox" name="cuisine" value="lebanese" checked><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Lebanese</label>
      <label class="mx-chip"><input type="checkbox" name="cuisine" value="thai"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Thai</label>
      <label class="mx-chip"><input type="checkbox" name="cuisine" value="ethiopian"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Ethiopian</label>
      <label class="mx-chip"><input type="checkbox" name="cuisine" value="georgian" checked><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Georgian</label>
      <label class="mx-chip"><input type="checkbox" name="cuisine" value="peruvian"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Peruvian</label>
      <label class="mx-chip"><input type="checkbox" name="cuisine" value="korean" checked><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Korean</label>
      <label class="mx-chip"><input type="checkbox" name="cuisine" value="vegan"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Plant-based</label>
    </div>
    <p class="mx-status"><span class="mx-sum" aria-hidden="true"></span><span class="mx-any">Showing every cuisine</span><button type="reset" class="mx-btn ghost">Reset</button></p>
  </fieldset>
</form>
</div></div>
CSS
/* CSS-only multiselects, no JavaScript. A: real checkboxes in a popover opened by popovertarget; CSS counters count the
   ticked boxes and :has() swaps the trigger text. The popover stays rendered (hidden) while closed so the counter keeps
   counting, and anchor positioning (the popover's implicit anchor is its button) puts it underneath. B: checkbox chips with the same counter.
   Reset is a type="reset" button: it restores the ticks the page loaded with, so give each multiselect its own <form>. */
.mx{--mx-accent:#a21caf;--mx-tint:#fbeefc;--mx-ring:rgba(162,28,175,.25);--mx-line:#8f8595;--mx-ink:#25152a;--mx-muted:#66596b;
  --mx-tick:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m3.5 8.5 3 3 6-7'/%3E%3C/svg%3E");
  display:grid;gap:7px;min-width:0;color:var(--mx-ink)}
.mx .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.mx-label{padding:0;font-size:.9rem;font-weight:600}
/* A: the trigger, with the count laid over it in the same grid cell */
.mx-wrap{display:grid;counter-reset:mx-on mx-all}
.mx-trigger{grid-area:1/1;display:flex;align-items:center;gap:10px;height:46px;padding:0 14px;font:inherit;font-size:.95rem;color:var(--mx-muted);text-align:left;
  background:#fff;border:1px solid var(--mx-line);border-radius:12px;box-shadow:0 1px 2px rgba(37,21,42,.06);cursor:pointer;
  transition:border-color .15s,box-shadow .15s}
.mx-trigger:hover{border-color:#6d6373}
.mx-trigger:focus-visible,.mx-wrap:has(.mx-pop:popover-open) .mx-trigger{outline:none;border-color:var(--mx-accent);box-shadow:0 0 0 4px var(--mx-ring)}
.mx-some{display:none;color:var(--mx-ink)}
.mx-wrap:has(:checked) .mx-trigger{padding-left:48px}
.mx-wrap:has(:checked) .mx-some{display:inline}
.mx-wrap:has(:checked) .mx-none{display:none}
.mx-chev{flex:none;width:16px;height:16px;margin-left:auto;color:var(--mx-muted);transition:rotate .2s}
.mx-wrap:has(.mx-pop:popover-open) .mx-chev{rotate:180deg}
.mx-count{grid-area:1/1;align-self:center;justify-self:start;display:none;place-items:center;min-width:24px;height:24px;margin-left:14px;padding:0 7px;
  border-radius:999px;background:var(--mx-accent);color:#fff;font-size:.78rem;font-weight:700;pointer-events:none}
.mx-count::after{content:counter(mx-on)}
.mx-wrap:has(:checked) .mx-count{display:grid}
/* the popover: always rendered so the counters work, hidden until open */
.mx-pop{display:block;visibility:hidden;opacity:0;translate:0 -4px;width:min(100% - 32px,340px);margin:auto;padding:6px;color:var(--mx-ink);background:#fff;
  border:1px solid #e3d6e6;border-radius:14px;box-shadow:0 18px 40px -12px rgba(37,21,42,.32);
  transition:opacity .15s,translate .15s,visibility .15s}
.mx-pop:popover-open{visibility:visible;opacity:1;translate:0 0}
@supports (position-area: block-end) {
  .mx-pop{position-area:block-end span-inline-end;position-try-fallbacks:flip-block;inset:auto;margin:6px 0;width:anchor-size(width);min-width:260px}
}
.mx-set{min-width:0;border:0;max-height:270px;overflow-y:auto;overscroll-behavior:contain}
.mx-opt{display:flex;align-items:center;gap:11px;padding:8px 10px;border-radius:8px;font-size:.93rem;cursor:pointer}
.mx-opt:hover,.mx-opt:has(:focus-visible){background:var(--mx-tint)}
.mx-opt:has(:checked){font-weight:600}
.mx-opt input,.mx-chip input{counter-increment:mx-all}
.mx-opt input:checked,.mx-chip input:checked{counter-increment:mx-all mx-on}
.mx-opt input{-webkit-appearance:none;appearance:none;flex:none;width:18px;height:18px;margin:0;border:1.5px solid #807584;border-radius:5px;background:#fff center/13px no-repeat;cursor:pointer}
.mx-opt input:checked{background-color:var(--mx-accent);background-image:var(--mx-tick);border-color:var(--mx-accent)}
.mx-opt input:focus-visible{outline:2px solid var(--mx-accent);outline-offset:2px}
.mx-price{margin-left:auto;font-size:.82rem;font-weight:400;color:var(--mx-muted);font-variant-numeric:tabular-nums}
.mx-foot{display:flex;align-items:center;gap:8px;padding:10px 6px 4px 10px;margin-top:6px;border-top:1px solid #eee2f0}
.mx-total{margin-right:auto;font-size:.82rem;color:var(--mx-muted)}
.mx-total::after{content:counter(mx-on) " of " counter(mx-all) " selected"}
.mx-btn{height:34px;padding:0 14px;font:inherit;font-size:.85rem;font-weight:600;border-radius:9px;cursor:pointer}
.mx-btn.ghost{color:var(--mx-accent);background:none;border:0}
.mx-btn.ghost:hover{background:var(--mx-tint)}
.mx-btn.solid{color:#fff;background:var(--mx-accent);border:1px solid var(--mx-accent)}
.mx-btn.solid:hover{background:#86198f}
.mx-btn:focus-visible{outline:2px solid var(--mx-accent);outline-offset:2px}
/* B: checkbox chips */
.mx-chips{min-width:0;border:0;counter-reset:mx-on mx-all;display:grid;gap:10px}
.mx-chips>legend{margin-bottom:10px}
.mx-chiplist{display:flex;flex-wrap:wrap;gap:8px}
.mx-chip{position:relative;display:inline-flex;align-items:center;gap:6px;height:36px;padding:0 14px;font-size:.9rem;font-weight:500;
  background:#fff;border:1px solid var(--mx-line);border-radius:999px;cursor:pointer;transition:background-color .15s,border-color .15s}
.mx-chip:hover{border-color:#6d6373}
.mx-chip input{position:absolute;opacity:0;width:1px;height:1px;margin:0;pointer-events:none}
.mx-chip svg{display:none;width:14px;height:14px;margin-left:-3px}
.mx-chip:has(:checked){padding-left:12px;color:#701a75;font-weight:600;background:var(--mx-tint);border-color:var(--mx-accent)}
.mx-chip:has(:checked) svg{display:block}
.mx-chip:has(:focus-visible){outline:2px solid var(--mx-accent);outline-offset:2px}
.mx-status{display:flex;align-items:center;gap:10px;min-height:34px;font-size:.84rem;color:var(--mx-muted)}
.mx-sum{display:none}
.mx-sum::after{content:counter(mx-on) " of " counter(mx-all) " cuisines selected"}
.mx-chips:has(:checked) .mx-sum{display:inline}
.mx-chips:has(:checked) .mx-any,.mx-chips:not(:has(:checked)) .mx-status .mx-btn{display:none}
@media (prefers-reduced-motion:reduce){.mx-trigger,.mx-chev,.mx-pop,.mx-chip{transition:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Popover checklist with a live count</span><div class="card demo-card"><div class="card-body">
<form class="mx" action="#">
  <span class="mx-label" id="mx-top-label">Extra toppings</span>
  <div class="mx-wrap">
    <button type="button" class="form-select mx-trigger d-flex align-items-center" popovertarget="mx-top" aria-labelledby="mx-top-label">
      <span class="mx-none">None yet</span><span class="mx-some">selected</span>
      <svg class="mx-chev" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m4 6 4 4 4-4"/></svg>
    </button>
    <div class="dropdown-menu mx-pop" id="mx-top" popover>
      <fieldset class="mx-set">
        <legend class="visually-hidden">Extra toppings</legend>
        <label class="dropdown-item mx-opt d-flex align-items-center"><input class="form-check-input" type="checkbox" name="toppings" value="mozzarella" checked> Buffalo mozzarella <span class="mx-price">+€2.00</span></label>
        <label class="dropdown-item mx-opt d-flex align-items-center"><input class="form-check-input" type="checkbox" name="toppings" value="basil" checked> Fresh basil <span class="mx-price">+€0.50</span></label>
        <label class="dropdown-item mx-opt d-flex align-items-center"><input class="form-check-input" type="checkbox" name="toppings" value="mushrooms"> Roasted mushrooms <span class="mx-price">+€1.50</span></label>
        <label class="dropdown-item mx-opt d-flex align-items-center"><input class="form-check-input" type="checkbox" name="toppings" value="olives"> Kalamata olives <span class="mx-price">+€1.00</span></label>
        <label class="dropdown-item mx-opt d-flex align-items-center"><input class="form-check-input" type="checkbox" name="toppings" value="nduja" checked> Spicy nduja <span class="mx-price">+€2.50</span></label>
        <label class="dropdown-item mx-opt d-flex align-items-center"><input class="form-check-input" type="checkbox" name="toppings" value="peppers"> Roasted peppers <span class="mx-price">+€1.20</span></label>
        <label class="dropdown-item mx-opt d-flex align-items-center"><input class="form-check-input" type="checkbox" name="toppings" value="anchovies"> Anchovies <span class="mx-price">+€1.80</span></label>
        <label class="dropdown-item mx-opt d-flex align-items-center"><input class="form-check-input" type="checkbox" name="toppings" value="rocket"> Wild rocket <span class="mx-price">+€0.80</span></label>
      </fieldset>
      <div class="mx-foot d-flex align-items-center">
        <span class="mx-total" aria-hidden="true"></span>
        <button type="reset" class="btn btn-link mx-btn mx-ghost">Reset</button>
        <button type="button" class="btn mx-btn mx-solid" popovertarget="mx-top" popovertargetaction="hide">Done</button>
      </div>
    </div>
    <span class="badge rounded-pill mx-count" aria-hidden="true"></span>
  </div>
</form>
</div></div></div>

<div><span class="lbl">Checkbox chips with a live count</span><div class="card demo-card"><div class="card-body">
<form class="mx" action="#">
  <fieldset class="mx-chips">
    <legend class="mx-label">Cuisine</legend>
    <div class="d-flex flex-wrap gap-2">
      <input type="checkbox" class="btn-check" id="mx-c-italian" name="cuisine" value="italian" autocomplete="off"><label class="btn mx-chip" for="mx-c-italian"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Italian</label>
      <input type="checkbox" class="btn-check" id="mx-c-japanese" name="cuisine" value="japanese" autocomplete="off" checked><label class="btn mx-chip" for="mx-c-japanese"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Japanese</label>
      <input type="checkbox" class="btn-check" id="mx-c-mexican" name="cuisine" value="mexican" autocomplete="off"><label class="btn mx-chip" for="mx-c-mexican"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Mexican</label>
      <input type="checkbox" class="btn-check" id="mx-c-lebanese" name="cuisine" value="lebanese" autocomplete="off" checked><label class="btn mx-chip" for="mx-c-lebanese"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Lebanese</label>
      <input type="checkbox" class="btn-check" id="mx-c-thai" name="cuisine" value="thai" autocomplete="off"><label class="btn mx-chip" for="mx-c-thai"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Thai</label>
      <input type="checkbox" class="btn-check" id="mx-c-ethiopian" name="cuisine" value="ethiopian" autocomplete="off"><label class="btn mx-chip" for="mx-c-ethiopian"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Ethiopian</label>
      <input type="checkbox" class="btn-check" id="mx-c-georgian" name="cuisine" value="georgian" autocomplete="off" checked><label class="btn mx-chip" for="mx-c-georgian"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Georgian</label>
      <input type="checkbox" class="btn-check" id="mx-c-peruvian" name="cuisine" value="peruvian" autocomplete="off"><label class="btn mx-chip" for="mx-c-peruvian"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Peruvian</label>
      <input type="checkbox" class="btn-check" id="mx-c-korean" name="cuisine" value="korean" autocomplete="off" checked><label class="btn mx-chip" for="mx-c-korean"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Korean</label>
      <input type="checkbox" class="btn-check" id="mx-c-vegan" name="cuisine" value="vegan" autocomplete="off"><label class="btn mx-chip" for="mx-c-vegan"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Plant-based</label>
    </div>
    <p class="mx-status d-flex align-items-center"><span class="mx-sum" aria-hidden="true"></span><span class="mx-any">Showing every cuisine</span><button type="reset" class="btn btn-link mx-btn mx-ghost">Reset</button></p>
  </fieldset>
</form>
</div></div></div>
CSS
/* CSS-only multiselects on Bootstrap parts, no JavaScript. A: .form-check-input checkboxes in a .dropdown-menu popover
   opened by popovertarget; CSS counters count the ticked boxes and :has() swaps the trigger text. The popover stays
   rendered (hidden) while closed so the counter keeps counting, and anchor positioning puts it under its button (the
   popover's implicit anchor). B: .btn-check chips with the same counter. Reset restores the ticks the page loaded with. */
.mx{--mx-accent:#a21caf;--mx-tint:#fbeefc;--mx-ring:rgba(162,28,175,.25);--mx-line:#8f8595;--mx-ink:#25152a;--mx-muted:#66596b;
  --mx-tick:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m3.5 8.5 3 3 6-7'/%3E%3C/svg%3E");
  display:grid;gap:7px;min-width:0;color:var(--mx-ink)}
.mx-label{margin:0;font-size:.9rem;font-weight:600}
.mx-wrap{display:grid;counter-reset:mx-on mx-all}
.mx .mx-trigger{--bs-form-select-bg-img:none;grid-area:1/1;gap:10px;height:46px;padding:0 14px;font-size:.95rem;line-height:1.45;color:var(--mx-muted);text-align:left;
  border-color:var(--mx-line);border-radius:12px;box-shadow:0 1px 2px rgba(37,21,42,.06);cursor:pointer}
.mx .mx-trigger:hover{border-color:#6d6373}
.mx .mx-trigger:focus{border-color:var(--mx-line);box-shadow:0 1px 2px rgba(37,21,42,.06)}
.mx .mx-trigger:focus-visible,.mx-wrap:has(.mx-pop:popover-open) .mx-trigger{border-color:var(--mx-accent);box-shadow:0 0 0 4px var(--mx-ring)}
.mx-some{display:none;color:var(--mx-ink)}
.mx .mx-wrap:has(:checked) .mx-trigger{padding-left:48px}
.mx-wrap:has(:checked) .mx-some{display:inline}
.mx-wrap:has(:checked) .mx-none{display:none}
.mx-chev{flex:none;width:16px;height:16px;margin-left:auto;color:var(--mx-muted);transition:rotate .2s}
.mx-wrap:has(.mx-pop:popover-open) .mx-chev{rotate:180deg}
.mx .mx-count{grid-area:1/1;align-self:center;justify-self:start;display:none;min-width:24px;margin-left:14px;padding:.4em .6em;background:var(--mx-accent);font-size:.78rem;pointer-events:none}
.mx-count::after{content:counter(mx-on)}
.mx-wrap:has(:checked) .mx-count{display:inline-block}
.mx .mx-pop{--bs-dropdown-padding-x:6px;--bs-dropdown-padding-y:6px;--bs-dropdown-border-color:#e3d6e6;--bs-dropdown-border-radius:14px;
  --bs-dropdown-link-color:var(--mx-ink);--bs-dropdown-link-hover-color:var(--mx-ink);--bs-dropdown-link-hover-bg:var(--mx-tint);
  --bs-dropdown-link-active-color:var(--mx-ink);--bs-dropdown-link-active-bg:var(--mx-tint);
  position:fixed;display:block;visibility:hidden;opacity:0;translate:0 -4px;inset:0;width:min(100% - 32px,340px);height:fit-content;margin:auto;
  box-shadow:0 18px 40px -12px rgba(37,21,42,.32);transition:opacity .15s,translate .15s,visibility .15s}
.mx .mx-pop:popover-open{visibility:visible;opacity:1;translate:0 0}
@supports (position-area: block-end) {
  .mx .mx-pop{position-area:block-end span-inline-end;position-try-fallbacks:flip-block;inset:auto;margin:6px 0;width:anchor-size(width);min-width:260px}
}
.mx-set{max-height:270px;overflow-y:auto;overscroll-behavior:contain}
.mx .mx-opt{gap:11px;padding:8px 10px;border-radius:8px;font-size:.93rem;white-space:normal;cursor:pointer}
.mx .mx-opt:has(:focus-visible){background:var(--mx-tint)}
.mx .mx-opt:has(:checked){font-weight:600}
.mx-opt .form-check-input,.mx-chips .btn-check{counter-increment:mx-all}
.mx-opt .form-check-input:checked,.mx-chips .btn-check:checked{counter-increment:mx-all mx-on}
.mx .mx-opt .form-check-input{flex:none;width:18px;height:18px;margin:0;border:1.5px solid #807584;border-radius:5px;background-size:13px;cursor:pointer}
.mx .mx-opt .form-check-input:checked{--bs-form-check-bg-image:var(--mx-tick);background-color:var(--mx-accent);border-color:var(--mx-accent)}
.mx .mx-opt .form-check-input:focus{box-shadow:none}
.mx .mx-opt .form-check-input:focus-visible{outline:2px solid var(--mx-accent);outline-offset:2px}
.mx-price{margin-left:auto;font-size:.82rem;font-weight:400;color:var(--mx-muted);font-variant-numeric:tabular-nums}
.mx-foot{gap:8px;padding:10px 6px 4px 10px;margin-top:6px;border-top:1px solid #eee2f0}
.mx-total{margin-right:auto;font-size:.82rem;color:var(--mx-muted)}
.mx-total::after{content:counter(mx-on) " of " counter(mx-all) " selected"}
.mx .mx-btn{--bs-btn-padding-x:14px;--bs-btn-font-size:.85rem;--bs-btn-font-weight:600;--bs-btn-border-radius:9px;--bs-btn-focus-box-shadow:none;height:34px}
.mx .mx-btn:focus-visible{outline:2px solid var(--mx-accent);outline-offset:2px}
.mx .mx-ghost{--bs-btn-color:var(--mx-accent);--bs-btn-hover-color:var(--mx-accent);--bs-btn-hover-bg:var(--mx-tint);--bs-btn-active-color:var(--mx-accent);--bs-btn-active-bg:var(--mx-tint);text-decoration:none}
.mx .mx-solid{--bs-btn-color:#fff;--bs-btn-bg:var(--mx-accent);--bs-btn-border-color:var(--mx-accent);--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#86198f;--bs-btn-hover-border-color:#86198f;
  --bs-btn-active-color:#fff;--bs-btn-active-bg:#86198f;--bs-btn-active-border-color:#86198f}
.mx-chips{min-width:0;counter-reset:mx-on mx-all;display:grid;gap:10px}
.mx-chips>legend{float:none;margin-bottom:10px}
.mx .mx-chip{--bs-btn-padding-x:14px;--bs-btn-font-size:.9rem;--bs-btn-font-weight:500;--bs-btn-color:var(--mx-ink);--bs-btn-bg:#fff;--bs-btn-border-color:var(--mx-line);
  --bs-btn-hover-color:var(--mx-ink);--bs-btn-hover-bg:#fff;--bs-btn-hover-border-color:#6d6373;--bs-btn-active-color:#701a75;--bs-btn-active-bg:var(--mx-tint);
  --bs-btn-active-border-color:var(--mx-accent);--bs-btn-focus-box-shadow:none;display:inline-flex;align-items:center;gap:6px;height:36px;border-radius:999px}
.mx .btn-check:checked+.mx-chip{padding-left:12px;font-weight:600}
.mx .btn-check:focus-visible+.mx-chip{outline:2px solid var(--mx-accent);outline-offset:2px}
.mx-chip svg{display:none;width:14px;height:14px;margin-left:-3px}
.btn-check:checked+.mx-chip svg{display:block}
.mx-status{gap:10px;min-height:34px;margin:0;font-size:.84rem;color:var(--mx-muted)}
.mx-sum{display:none}
.mx-sum::after{content:counter(mx-on) " of " counter(mx-all) " cuisines selected"}
.mx-chips:has(:checked) .mx-sum{display:inline}
.mx-chips:has(:checked) .mx-any,.mx-chips:not(:has(:checked)) .mx-status .btn{display:none}
@media (prefers-reduced-motion:reduce){.mx .mx-pop,.mx-chev,.mx .btn{transition:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-[#66596b] uppercase">Popover checklist with a live count</span><div class="rounded-2xl border border-[#eee2f0] bg-white px-6 pt-[22px] pb-6 shadow-[0_1px_2px_rgba(37,21,42,.04)]">
<form class="grid min-w-0 gap-[7px] text-mx-ink" action="#">
  <span class="text-[.9rem] font-semibold" id="mx-top-label">Extra toppings</span>
  <div class="group/mx grid [counter-reset:mx-on_mx-all]">
    <button type="button" class="group/btn col-start-1 row-start-1 flex h-[46px] cursor-pointer items-center gap-2.5 rounded-xl border border-mx-line bg-white px-3.5 text-left text-[.95rem] text-mx-muted shadow-[0_1px_2px_rgba(37,21,42,.06)] transition-[border-color,box-shadow] duration-150 group-has-checked/mx:pl-12 hover:border-[#6d6373] focus-visible:border-mx-accent focus-visible:shadow-[0_0_0_4px_rgba(162,28,175,.25)] focus-visible:outline-none group-has-[:popover-open]/mx:border-mx-accent group-has-[:popover-open]/mx:shadow-[0_0_0_4px_rgba(162,28,175,.25)] motion-reduce:transition-none" popovertarget="mx-top" aria-labelledby="mx-top-label">
      <span class="group-has-checked/mx:hidden">None yet</span><span class="hidden text-mx-ink group-has-checked/mx:inline">selected</span>
      <svg class="ml-auto size-4 flex-none text-mx-muted transition-[rotate] duration-200 group-has-[:popover-open]/mx:rotate-180 motion-reduce:transition-none" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m4 6 4 4 4-4"/></svg>
    </button>
    <div class="invisible fixed inset-0 m-auto block h-fit w-[min(100%-32px,340px)] -translate-y-1 rounded-[14px] border border-[#e3d6e6] bg-white p-1.5 text-mx-ink opacity-0 shadow-[0_18px_40px_-12px_rgba(37,21,42,.32)] transition-[opacity,translate,visibility] duration-150 open:visible open:translate-y-0 open:opacity-100 motion-reduce:transition-none supports-[position-area:block-end]:inset-auto supports-[position-area:block-end]:mx-0 supports-[position-area:block-end]:my-1.5 supports-[position-area:block-end]:w-[anchor-size(width)] supports-[position-area:block-end]:min-w-[260px] supports-[position-area:block-end]:[position-area:block-end_span-inline-end] supports-[position-area:block-end]:[position-try-fallbacks:flip-block]" id="mx-top" popover>
      <fieldset class="max-h-[270px] min-w-0 overflow-y-auto overscroll-contain">
        <legend class="sr-only">Extra toppings</legend>
        <label class="flex cursor-pointer items-center gap-[11px] rounded-lg px-2.5 py-2 text-[.93rem] hover:bg-mx-tint has-checked:font-semibold has-focus-visible:bg-mx-tint"><input class="size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-[#807584] bg-white bg-size-[13px] bg-center bg-no-repeat [counter-increment:mx-all] checked:mx-tick checked:border-mx-accent checked:bg-mx-accent checked:[counter-increment:mx-all_mx-on] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" type="checkbox" name="toppings" value="mozzarella" checked> Buffalo mozzarella <span class="ml-auto text-[.82rem] font-normal text-mx-muted tabular-nums">+€2.00</span></label>
        <label class="flex cursor-pointer items-center gap-[11px] rounded-lg px-2.5 py-2 text-[.93rem] hover:bg-mx-tint has-checked:font-semibold has-focus-visible:bg-mx-tint"><input class="size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-[#807584] bg-white bg-size-[13px] bg-center bg-no-repeat [counter-increment:mx-all] checked:mx-tick checked:border-mx-accent checked:bg-mx-accent checked:[counter-increment:mx-all_mx-on] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" type="checkbox" name="toppings" value="basil" checked> Fresh basil <span class="ml-auto text-[.82rem] font-normal text-mx-muted tabular-nums">+€0.50</span></label>
        <label class="flex cursor-pointer items-center gap-[11px] rounded-lg px-2.5 py-2 text-[.93rem] hover:bg-mx-tint has-checked:font-semibold has-focus-visible:bg-mx-tint"><input class="size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-[#807584] bg-white bg-size-[13px] bg-center bg-no-repeat [counter-increment:mx-all] checked:mx-tick checked:border-mx-accent checked:bg-mx-accent checked:[counter-increment:mx-all_mx-on] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" type="checkbox" name="toppings" value="mushrooms"> Roasted mushrooms <span class="ml-auto text-[.82rem] font-normal text-mx-muted tabular-nums">+€1.50</span></label>
        <label class="flex cursor-pointer items-center gap-[11px] rounded-lg px-2.5 py-2 text-[.93rem] hover:bg-mx-tint has-checked:font-semibold has-focus-visible:bg-mx-tint"><input class="size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-[#807584] bg-white bg-size-[13px] bg-center bg-no-repeat [counter-increment:mx-all] checked:mx-tick checked:border-mx-accent checked:bg-mx-accent checked:[counter-increment:mx-all_mx-on] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" type="checkbox" name="toppings" value="olives"> Kalamata olives <span class="ml-auto text-[.82rem] font-normal text-mx-muted tabular-nums">+€1.00</span></label>
        <label class="flex cursor-pointer items-center gap-[11px] rounded-lg px-2.5 py-2 text-[.93rem] hover:bg-mx-tint has-checked:font-semibold has-focus-visible:bg-mx-tint"><input class="size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-[#807584] bg-white bg-size-[13px] bg-center bg-no-repeat [counter-increment:mx-all] checked:mx-tick checked:border-mx-accent checked:bg-mx-accent checked:[counter-increment:mx-all_mx-on] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" type="checkbox" name="toppings" value="nduja" checked> Spicy nduja <span class="ml-auto text-[.82rem] font-normal text-mx-muted tabular-nums">+€2.50</span></label>
        <label class="flex cursor-pointer items-center gap-[11px] rounded-lg px-2.5 py-2 text-[.93rem] hover:bg-mx-tint has-checked:font-semibold has-focus-visible:bg-mx-tint"><input class="size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-[#807584] bg-white bg-size-[13px] bg-center bg-no-repeat [counter-increment:mx-all] checked:mx-tick checked:border-mx-accent checked:bg-mx-accent checked:[counter-increment:mx-all_mx-on] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" type="checkbox" name="toppings" value="peppers"> Roasted peppers <span class="ml-auto text-[.82rem] font-normal text-mx-muted tabular-nums">+€1.20</span></label>
        <label class="flex cursor-pointer items-center gap-[11px] rounded-lg px-2.5 py-2 text-[.93rem] hover:bg-mx-tint has-checked:font-semibold has-focus-visible:bg-mx-tint"><input class="size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-[#807584] bg-white bg-size-[13px] bg-center bg-no-repeat [counter-increment:mx-all] checked:mx-tick checked:border-mx-accent checked:bg-mx-accent checked:[counter-increment:mx-all_mx-on] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" type="checkbox" name="toppings" value="anchovies"> Anchovies <span class="ml-auto text-[.82rem] font-normal text-mx-muted tabular-nums">+€1.80</span></label>
        <label class="flex cursor-pointer items-center gap-[11px] rounded-lg px-2.5 py-2 text-[.93rem] hover:bg-mx-tint has-checked:font-semibold has-focus-visible:bg-mx-tint"><input class="size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-[#807584] bg-white bg-size-[13px] bg-center bg-no-repeat [counter-increment:mx-all] checked:mx-tick checked:border-mx-accent checked:bg-mx-accent checked:[counter-increment:mx-all_mx-on] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" type="checkbox" name="toppings" value="rocket"> Wild rocket <span class="ml-auto text-[.82rem] font-normal text-mx-muted tabular-nums">+€0.80</span></label>
      </fieldset>
      <div class="mt-1.5 flex items-center gap-2 border-t border-[#eee2f0] pt-2.5 pr-1.5 pb-1 pl-2.5">
        <span class="mr-auto text-[.82rem] text-mx-muted after:content-[counter(mx-on)_'_of_'_counter(mx-all)_'_selected']" aria-hidden="true"></span>
        <button type="reset" class="h-[34px] cursor-pointer rounded-[9px] px-3.5 text-[.85rem] font-semibold text-mx-accent hover:bg-mx-tint focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent">Reset</button>
        <button type="button" class="h-[34px] cursor-pointer rounded-[9px] border border-mx-accent bg-mx-accent px-3.5 text-[.85rem] font-semibold text-white hover:bg-mx-strong focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" popovertarget="mx-top" popovertargetaction="hide">Done</button>
      </div>
    </div>
    <span class="pointer-events-none col-start-1 row-start-1 ml-3.5 hidden h-6 min-w-6 place-items-center self-center justify-self-start rounded-full bg-mx-accent px-[7px] text-[.78rem] font-bold text-white group-has-checked/mx:grid after:content-[counter(mx-on)]" aria-hidden="true"></span>
  </div>
</form>
</div></div>

<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-[#66596b] uppercase">Checkbox chips with a live count</span><div class="rounded-2xl border border-[#eee2f0] bg-white px-6 pt-[22px] pb-6 shadow-[0_1px_2px_rgba(37,21,42,.04)]">
<form class="grid min-w-0 gap-[7px] text-mx-ink" action="#">
  <fieldset class="group/chips grid min-w-0 gap-2.5 [counter-reset:mx-on_mx-all]">
    <legend class="mb-2.5 text-[.9rem] font-semibold">Cuisine</legend>
    <div class="flex flex-wrap gap-2">
      <label class="group relative inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-mx-line bg-white px-3.5 text-[.9rem] font-medium transition-[background-color,border-color] duration-150 hover:border-[#6d6373] has-checked:border-mx-accent has-checked:bg-mx-tint has-checked:pl-3 has-checked:font-semibold has-checked:text-[#701a75] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-mx-accent motion-reduce:transition-none"><input class="pointer-events-none absolute m-0 size-px opacity-0 [counter-increment:mx-all] checked:[counter-increment:mx-all_mx-on]" type="checkbox" name="cuisine" value="italian"><svg class="-ml-[3px] hidden size-3.5 group-has-checked:block" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Italian</label>
      <label class="group relative inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-mx-line bg-white px-3.5 text-[.9rem] font-medium transition-[background-color,border-color] duration-150 hover:border-[#6d6373] has-checked:border-mx-accent has-checked:bg-mx-tint has-checked:pl-3 has-checked:font-semibold has-checked:text-[#701a75] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-mx-accent motion-reduce:transition-none"><input class="pointer-events-none absolute m-0 size-px opacity-0 [counter-increment:mx-all] checked:[counter-increment:mx-all_mx-on]" type="checkbox" name="cuisine" value="japanese" checked><svg class="-ml-[3px] hidden size-3.5 group-has-checked:block" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Japanese</label>
      <label class="group relative inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-mx-line bg-white px-3.5 text-[.9rem] font-medium transition-[background-color,border-color] duration-150 hover:border-[#6d6373] has-checked:border-mx-accent has-checked:bg-mx-tint has-checked:pl-3 has-checked:font-semibold has-checked:text-[#701a75] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-mx-accent motion-reduce:transition-none"><input class="pointer-events-none absolute m-0 size-px opacity-0 [counter-increment:mx-all] checked:[counter-increment:mx-all_mx-on]" type="checkbox" name="cuisine" value="mexican"><svg class="-ml-[3px] hidden size-3.5 group-has-checked:block" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Mexican</label>
      <label class="group relative inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-mx-line bg-white px-3.5 text-[.9rem] font-medium transition-[background-color,border-color] duration-150 hover:border-[#6d6373] has-checked:border-mx-accent has-checked:bg-mx-tint has-checked:pl-3 has-checked:font-semibold has-checked:text-[#701a75] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-mx-accent motion-reduce:transition-none"><input class="pointer-events-none absolute m-0 size-px opacity-0 [counter-increment:mx-all] checked:[counter-increment:mx-all_mx-on]" type="checkbox" name="cuisine" value="lebanese" checked><svg class="-ml-[3px] hidden size-3.5 group-has-checked:block" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Lebanese</label>
      <label class="group relative inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-mx-line bg-white px-3.5 text-[.9rem] font-medium transition-[background-color,border-color] duration-150 hover:border-[#6d6373] has-checked:border-mx-accent has-checked:bg-mx-tint has-checked:pl-3 has-checked:font-semibold has-checked:text-[#701a75] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-mx-accent motion-reduce:transition-none"><input class="pointer-events-none absolute m-0 size-px opacity-0 [counter-increment:mx-all] checked:[counter-increment:mx-all_mx-on]" type="checkbox" name="cuisine" value="thai"><svg class="-ml-[3px] hidden size-3.5 group-has-checked:block" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Thai</label>
      <label class="group relative inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-mx-line bg-white px-3.5 text-[.9rem] font-medium transition-[background-color,border-color] duration-150 hover:border-[#6d6373] has-checked:border-mx-accent has-checked:bg-mx-tint has-checked:pl-3 has-checked:font-semibold has-checked:text-[#701a75] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-mx-accent motion-reduce:transition-none"><input class="pointer-events-none absolute m-0 size-px opacity-0 [counter-increment:mx-all] checked:[counter-increment:mx-all_mx-on]" type="checkbox" name="cuisine" value="ethiopian"><svg class="-ml-[3px] hidden size-3.5 group-has-checked:block" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Ethiopian</label>
      <label class="group relative inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-mx-line bg-white px-3.5 text-[.9rem] font-medium transition-[background-color,border-color] duration-150 hover:border-[#6d6373] has-checked:border-mx-accent has-checked:bg-mx-tint has-checked:pl-3 has-checked:font-semibold has-checked:text-[#701a75] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-mx-accent motion-reduce:transition-none"><input class="pointer-events-none absolute m-0 size-px opacity-0 [counter-increment:mx-all] checked:[counter-increment:mx-all_mx-on]" type="checkbox" name="cuisine" value="georgian" checked><svg class="-ml-[3px] hidden size-3.5 group-has-checked:block" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Georgian</label>
      <label class="group relative inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-mx-line bg-white px-3.5 text-[.9rem] font-medium transition-[background-color,border-color] duration-150 hover:border-[#6d6373] has-checked:border-mx-accent has-checked:bg-mx-tint has-checked:pl-3 has-checked:font-semibold has-checked:text-[#701a75] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-mx-accent motion-reduce:transition-none"><input class="pointer-events-none absolute m-0 size-px opacity-0 [counter-increment:mx-all] checked:[counter-increment:mx-all_mx-on]" type="checkbox" name="cuisine" value="peruvian"><svg class="-ml-[3px] hidden size-3.5 group-has-checked:block" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Peruvian</label>
      <label class="group relative inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-mx-line bg-white px-3.5 text-[.9rem] font-medium transition-[background-color,border-color] duration-150 hover:border-[#6d6373] has-checked:border-mx-accent has-checked:bg-mx-tint has-checked:pl-3 has-checked:font-semibold has-checked:text-[#701a75] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-mx-accent motion-reduce:transition-none"><input class="pointer-events-none absolute m-0 size-px opacity-0 [counter-increment:mx-all] checked:[counter-increment:mx-all_mx-on]" type="checkbox" name="cuisine" value="korean" checked><svg class="-ml-[3px] hidden size-3.5 group-has-checked:block" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Korean</label>
      <label class="group relative inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-mx-line bg-white px-3.5 text-[.9rem] font-medium transition-[background-color,border-color] duration-150 hover:border-[#6d6373] has-checked:border-mx-accent has-checked:bg-mx-tint has-checked:pl-3 has-checked:font-semibold has-checked:text-[#701a75] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-mx-accent motion-reduce:transition-none"><input class="pointer-events-none absolute m-0 size-px opacity-0 [counter-increment:mx-all] checked:[counter-increment:mx-all_mx-on]" type="checkbox" name="cuisine" value="vegan"><svg class="-ml-[3px] hidden size-3.5 group-has-checked:block" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m3.5 8.5 3 3 6-7"/></svg>Plant-based</label>
    </div>
    <p class="flex min-h-[34px] items-center gap-2.5 text-[.84rem] text-mx-muted"><span class="hidden group-has-checked/chips:inline after:content-[counter(mx-on)_'_of_'_counter(mx-all)_'_cuisines_selected']" aria-hidden="true"></span><span class="group-has-checked/chips:hidden">Showing every cuisine</span><button type="reset" class="hidden h-[34px] cursor-pointer rounded-[9px] px-3.5 text-[.85rem] font-semibold text-mx-accent group-has-checked/chips:inline-block hover:bg-mx-tint focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent">Reset</button></p>
  </fieldset>
</form>
</div></div>
CSS
@theme {
  --color-mx-accent: #a21caf;
  --color-mx-strong: #86198f;
  --color-mx-tint: #fbeefc;
  --color-mx-line: #8f8595;
  --color-mx-ink: #25152a;
  --color-mx-muted: #66596b;
}
/* the tick drawn inside a checked box */
@utility mx-tick { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m3.5 8.5 3 3 6-7'/%3E%3C/svg%3E"); }

About this set

Multiselects that run on HTML and CSS alone, with no script at all. Popover checklist with a live count is a pizza toppings dropdown: a button with popovertarget opens a popover of real checkboxes with prices, a CSS counter shows how many are ticked both in a badge on the button and as 3 of 8 selected in the footer, :has() swaps the button text between None yet and selected, and Done closes the popover. The popover stays rendered while closed, hidden with visibility, so the counter keeps counting, and anchor positioning places it under its button, which is its implicit anchor. Checkbox chips with a live count is a cuisine filter of pill-shaped checkboxes that fill and show a tick when picked, with a 4 of 10 cuisines selected line underneath. Both have a reset button that restores the ticks the page loaded with. Because the inputs are ordinary checkboxes, the form submits them as usual, Escape and clicking outside close the popover, and focus returns to the button.

What’s included

  • No JavaScript
  • Popover opened with popovertarget and placed with anchor positioning
  • Live counts from CSS counters
  • Trigger text and chip states driven by :has()
  • Real checkboxes that submit with the form

Accessibility

The checkboxes are real inputs inside a fieldset with a legend, so each one announces its own state; the button is labelled by the visible label and the browser reports its expanded state for the popover. The counts are drawn by CSS and are hidden from screen readers, so they add no information that is not already on the checkboxes. Focus shows an outline on the button, on each checkbox and around each chip, and the popover fade stops under prefers-reduced-motion.

Customise it

Change --mx-accent, --mx-tint and --mx-line on .mx; the tick is an SVG data URI in --mx-tick. In Tailwind edit the --color-mx-* theme colours; the counter names are mx-on and mx-all.