Checkbox Technical Notes

Submission Basics

  • A checked checkbox submits name=VALUE. If you don’t set value, browsers send on.

  • An unchecked checkbox submits nothing.

Change the submitted values

True value

Pick your “true” value with the value attribute:

<input type="checkbox" name="agree" value="1">

False value

To also send a “false” value when unchecked, use one of these:

  1. Hidden fallback (no JS; two controls with same name)

<input type="hidden"  name="agree" value="0">
<label><input type="checkbox" name="agree" value="1"> I agree</label>

Server receives agree=0 when unchecked, agree=0&agree=1 when checked (order = DOM order). If your backend can’t handle duplicate keys, disable the hidden input when checked:

  1. formdata hook (single definitive value)

  1. Handle on the server: treat missing key as false.

A11y checklist

  • Provide a real <label> (wrap or for). This is the accessible name and expands the click target.

  • Keep it a native <input type="checkbox">; don’t replace with divs. If styled as a toggle, keep checkbox semantics (no extra role).

  • Don’t rely on color alone for state; ensure a positional/icon change and visible focus outline.

  • Group related boxes with <fieldset><legend>…</legend></fieldset>.

  • Use required, aria-invalid, and an inline error message (referenced with aria-describedby) when applicable.

  • For tri-state use el.indeterminate = true (JS) if needed.

Using <legend>

<fieldset><legend> grouping

  • Purpose: programmatically group related controls (e.g., a set of checkboxes answering one question). Screen readers announce the legend as the group label when navigating within the group.

  • Rules:

    • Put one <legend> as the first child of <fieldset>.

    • Keep a meaningful legend that reads well before each inner control’s label.

    • Use when instructions/errors apply to the whole group.

Example with error/help

Notes

  • Do not replace native checkboxes with div + ARIA unless necessary. If you must, use role="checkbox", manage tabindex, Space toggling, and aria-checked="true|false|mixed".

  • Form reset clears indeterminate to false; reapply in your code if a mixed state should remain after reset.

Indeterminate State

Use cases???

  • Supported: yes, via the HTMLInputElement.indeterminate property (JS-only). There is no indeterminate HTML attribute.

  • Semantics: a visual “mixed/partial” state. It does not affect form submission; only checked submits.

  • Interaction: on user click/Space, browsers automatically set indeterminate = false and then toggle checked. Re-set it in code if needed.

  • Styling: use the :indeterminate CSS pseudo-class.

  • A11y: announced as “mixed” by modern AT; keep a clear label and optional help text.

Submitting a tri-state

  • Hidden fallback:

  • Or use the formdata event to set exactly one value (none/mixed/all).

Last updated