About this set
The checkbox states a real form needs and most snippets skip. A select-all parent shows the indeterminate state, a dash, while only some of its regions are checked; it checks or clears the whole group when clicked and updates itself as the children change. A disabled pair shows an unavailable option and an always-on option that is checked and disabled, both greyed out. An error example marks the terms checkbox with a red border and a message underneath. Indeterminate cannot be set in HTML, so the set includes a short script that reads the group from the parent’s aria-controls attribute and keeps parent and children in sync; the other states are pure CSS. The plain CSS version styles :indeterminate, :disabled and [aria-invalid] on a hidden input with a drawn sibling box. The Bootstrap version uses .form-check-input with its built-in indeterminate dash, .is-invalid and .invalid-feedback, with the disabled greys adjusted. The Tailwind version uses peer-indeterminate, peer-disabled and peer-aria-invalid variants.
What’s included
- Select-all parent with a working indeterminate state
- Disabled and checked-plus-disabled options
- Error state wired with aria-invalid and aria-describedby
- One small dependency-free script, shared by all three versions
- Bootstrap version uses .is-invalid and .invalid-feedback
Accessibility
Every checkbox has its visible text as the label. The indeterminate parent is set through the DOM property, so assistive technology announces it as mixed, and it points at its group with aria-controls. The error checkbox carries aria-invalid="true" and aria-describedby pointing at the message, so the message is read with the control. Focus shows a 2px blue outline, disabled inputs are skipped by the keyboard, and transitions stop under prefers-reduced-motion.
Customise it
Plain CSS: change #2563eb for checked and indeterminate, #dc2626 for the error, and the #f1f5f9/#cbd5e1 disabled greys. Bootstrap: set --choice-accent on .choice and --bs-form-invalid-color for the error red. Tailwind: swap blue-600, red-600 and the slate disabled classes.






