Accessibilitycriticalforms
Associate labels with form controls
rule · form-labels
Every form control must have a label that is programmatically associated with it to ensure it is accessible to all users. MDN's <label> reference (opens in a new tab) and WCAG form guidance both treat this as a baseline requirement, not an enhancement.
Code Examples
Correct Implementation
HTML
<label for="email-address">Email Address</label>
<input type="email" id="email-address" name="email">
<!-- Or wrapping the input -->
<label>
Email Address
<input type="email" name="email">
</label>Incorrect Implementation
HTML
<span>Email Address</span>
<input type="email" name="email">Why It Matters
- Assistive Technology: Screen readers announce the label when the user focuses on the input.
- Usability: Clicking the label moves focus to the input, providing a larger hit area for users with motor impairments or those on mobile devices.
- Form Validation: Browsers and tools can better associate error messages with the correct fields.
Best Practices
✅ Use for and id: This is the most robust way to associate labels.
HTML
<label for="first-name">First Name</label>
<input type="text" id="first-name">✅ Nested Labels: Alternatively, you can nest the input inside the label.
HTML
<label>
Last Name
<input type="text">
</label>❌ Avoid Placeholder-only labels: Placeholders disappear when the user types and are not a substitute for labels.
HTML
<!-- Avoid this -->
<input type="text" placeholder="First Name">✅ Use <fieldset> and <legend> for grouped controls: Radio buttons and related checkboxes need a programmatic group label, not just bold text above them.
HTML
<fieldset>
<legend>Preferred contact method</legend>
<label>
<input type="radio" name="contact" value="email">
Email
</label>
<label>
<input type="radio" name="contact" value="phone">
Phone
</label>
</fieldset>Exceptions
- Evaluate the rendered experience before treating a static-code smell as a blocker; interaction timing, browser behavior, and assistive technology output often determine severity.
- Not every secondary accessibility issue deserves equal weight; prioritize the issue that most directly blocks perception, operation, or understanding.
- Avoid adding redundant markup or ARIA solely to satisfy a rule when a simpler semantic implementation would eliminate the issue entirely.
Standards
- Align the implementation with W3C WAI: WCAG Overview and verify the rendered experience, not only the source code.
- Align the implementation with MDN: Accessibility and verify the rendered experience, not only the source code.
Verification
Automated Checks
- Inspect the browser accessibility tree or accessibility pane for the relevant element, role, or accessible name.
- Run an automated accessibility checker such as axe or Lighthouse where applicable.
Manual Checks
- Test the affected UI with keyboard-only navigation and confirm the rule holds in the rendered experience.
- Re-test one representative user flow with a screen reader if this rule affects a key interaction.
- Confirm every field still has a visible label after the user starts typing and after browser autofill runs.
- For radio groups and checkbox groups, confirm the shared question is announced before the individual control labels.