Under Construction: The content on this site draft material. It is not the official content of this site and should not be followed at this time.

Not Legal Advice: The content on this site is provided for informational purposes only and does not constitute legal advice. Consult a qualified attorney for advice specific to your situation.

Purpose

Checkboxes allow users to make binary selections, either individually or as part of a group. The indeterminate state is used for “select all” controls where a subset of children is selected.

Usage Guidance

  • Use native <input type="checkbox"> whenever possible
  • Group related checkboxes with <fieldset> and <legend>
  • Label every checkbox with an associated <label> element
  • Use indeterminate state only for “select all” scenarios

Accessibility Considerations

  • Native <input type="checkbox"> provides keyboard support and state announcement automatically
  • The <label> element must be explicitly associated (via for/id) or wrapping the input
  • indeterminate state must be set via JavaScript (checkbox.indeterminate = true)—there is no HTML attribute for it

Keyboard Support

Key Action
Tab / Shift+Tab Move focus to/from checkbox
Space Toggle checked state

Screen Reader Behavior

Screen readers announce “checkbox, checked/unchecked/mixed” and the label text. The indeterminate state is announced as “mixed” by most screen readers.

ARIA Requirements

  • Native HTML checkboxes require no ARIA
  • Custom checkboxes require role="checkbox" with aria-checked="true|false|mixed"
  • Group label requires aria-labelledby pointing to the group heading or use <fieldset>/<legend>

Common Mistakes

  • Custom checkboxes without keyboard support
  • Missing <label> association (using placeholder instead)
  • Not updating aria-checked on state change for custom controls
  • Forgetting aria-checked="mixed" for indeterminate state

Live Example

Select areas to include in audit scope:

Code Example

<fieldset>
  <legend>Select audit scope:</legend>
  
  <label>
    <input type="checkbox" name="scope" value="web" checked>
    Public-facing website
  </label>

  <label>
    <input type="checkbox" name="scope" value="mobile">
    Mobile application
  </label>
</fieldset>

<!-- Indeterminate state requires JavaScript -->
<script>
  document.getElementById('select-all').indeterminate = true;
</script>