All rules

Sheath rule

a11y-form-label

Form inputs must have associated labels for accessibility.
Package
Core
Default severity
error by default
Auto-fix
Manual fix

#Why

Labels help all users understand form fields, and are essential for screen reader users to know what information to enter. Labels also increase the clickable area for form controls, improving usability.

#Examples

#Bad

<!-- Input without any label -->
<input type="text" name="email">
<!-- Select without label -->
<select name="country">
<option>USA</option>
<option>Canada</option>
</select>
<!-- Textarea without label -->
<textarea name="message"></textarea>
<!-- Association alone is insufficient when the label has no name -->
<label for="reference"></label>
<input id="reference" name="reference">

#Good

<!-- Explicit label with for attribute -->
<label for="email">Email Address</label>
<input type="text" id="email" name="email">
<!-- Using aria-label -->
<input type="search" aria-label="Search products" name="q">
<!-- Using aria-labelledby -->
<span id="email-label">Email Address</span>
<input type="text" aria-labelledby="email-label" name="email">
<!-- Using title attribute -->
<input type="text" title="Enter your email" name="email">
<!-- Select with label -->
<label for="country">Country</label>
<select id="country" name="country">
<option>USA</option>
</select>
<!-- Textarea with label -->
<label for="message">Message</label>
<textarea id="message" name="message"></textarea>
<!-- Implicit label: wrapping the control associates it, no for/id needed -->
<label>
Email Address <input type="text" name="email">
</label>

#Notes

  • Hidden and non-rendered descendant text does not make a wrapping or referenced label visible, except when a hidden element is explicitly referenced through aria-labelledby.
  • Prefer <label for="id"> for best accessibility and usability
  • A <label> wrapping the control labels it implicitly (WCAG technique H44), so no for/id pair is required there
  • Associated labels must contain non-empty accessible content. Empty and whitespace-only labels leave the control unnamed.
  • A wrapping label implicitly labels only its first labelable descendant.
  • Hidden inputs (type="hidden") don't need labels
  • Submit, reset, button, and image inputs don't need labels (use value or alt instead)
  • Placeholder text is not a substitute for labels - it disappears when typing
  • Opaque attribute spreads such as {{ $attributes }} make the final label requirements unknowable and are not checked. Each explicit branch that produces an exposed input type requiring a label must have one

#References

#Related Rules