Skip to main content

Form inputs have labels

ab-002585 · project-snapshot.accessibility.form-inputs-have-labels
Severity: mediumactive

Why it matters

An <input> without <label htmlFor>, aria-label, or a wrapping <label> parent is announced by screen readers as "edit text" with no indication of what the field is for — on a checkout or signup form this turns every submission into a guessing game and drives abandonment. The most common anti-pattern is using the placeholder attribute as the sole label, which visually looks labeled to a sighted developer but disappears on focus, provides no accessible name, and forces users with cognitive or memory impairments to delete their input just to re-read the prompt. AI coding tools produce this failure constantly because modern Tailwind-shaped UI snippets often omit <label> in favor of placeholder text for visual compactness, and because form libraries that wire up labels via id wiring frequently lose the wiring when a model refactors a form. Browser autofill and password managers also rely on labels to decide what to autofill, so unlabeled fields quietly break password saving.

Severity rationale

Medium because unlabeled inputs block assistive-tech users from submitting forms and degrade autofill, but sighted users with working mice can still complete them; WCAG 2.2 SC 1.3.1 and 3.3.2 treat this as a Level A failure on content semantics rather than a security issue.

Remediation

Pair each input with a <label>:

<label htmlFor="email">Email</label>
<input id="email" name="email" type="email" />

Deeper remediation guidance and cross-reference coverage for this check lives in the accessibility-fundamentals Pro audit — run that after applying this fix for a more exhaustive pass on the same topic.

Detection

  • ID: project-snapshot.accessibility.form-inputs-have-labels
  • Severity: medium
  • What to look for: Enumerate every <input>, <textarea>, <select> in JSX/TSX (excluding type="hidden", type="submit", type="button"). For each, check whether one of the following is present: a <label htmlFor={id}> with matching id, an aria-label, an aria-labelledby, or being wrapped by a <label> parent.
  • Pass criteria: At least 90% of detected form inputs have an associated label via one of the four mechanisms.
  • Fail criteria: More than 10% of inputs are unlabeled.
  • Skip (N/A) when: No form inputs detected.
  • Do NOT pass when: A placeholder is used as the only label — placeholders disappear on focus and are not accessible.
  • Report even on pass: "Found N form inputs (excluding hidden/submit/button); M have associated labels. Coverage: M/N = X%."
  • Detail on fail: "6 of 32 form inputs lack labels (19% — should be under 10%); examples: components/search-bar.tsx:12, app/contact/page.tsx:24".
  • Remediation: Pair each input with a <label>:
    <label htmlFor="email">Email</label>
    <input id="email" name="email" type="email" />
    

Taxons

History