Placeholder text disappears when a user begins typing, leaving them with no reminder of what a field expects. Screen readers may not read placeholder text at all, or read it only once. When an input has no associated <label> or ARIA label, screen reader users hear only the input type—"edit text"—with no context about its purpose. WCAG 2.2 SC 1.3.1 (Level A) and SC 3.3.2 (Level A) both require inputs to have accessible names and purpose identification. Section 508 2018 Refresh 502.3.6 incorporates this. Every unlabeled form field is an enrollment, checkout, or support pathway rendered unusable for screen reader users.
High because unlabeled form inputs are directly unusable by screen reader users who cannot determine a field's purpose from type alone, blocking form submission workflows.
Associate every <input>, <textarea>, and <select> with a visible <label> element. Use htmlFor in React to bind them:
<label htmlFor="email">Email address</label>
<input id="email" type="email" placeholder="you@example.com" />
For inputs where a visible label cannot be shown (search bars in compact UIs), use aria-label:
<input
id="search"
type="search"
aria-label="Search products"
placeholder="Search…"
/>
For dynamically generated inputs or multi-step forms, use aria-labelledby to reference an existing heading or description:
<h2 id="step-title">Billing address</h2>
<input type="text" aria-labelledby="step-title" />
Placeholder text may supplement a label but never replace it.
gov-section-508.keyboard-assistive.form-labelshigh<input>, <textarea>, and <select> element. Each must have an associated <label> element with a for attribute matching the input's id, OR the input must have an aria-label or aria-labelledby attribute. Placeholder text alone does not count as a label for screen readers.<label for="id"> or an ARIA label attribute. At least 1 implementation must be verified.<label> or ARIA label."5 form inputs lack associated labels: email input uses placeholder='user@example.com', password input uses placeholder='Password', and 3 text inputs lack both labels and placeholders."<label htmlFor="email">Email Address</label>
<input id="email" type="email" />
Or use ARIA for dynamically generated inputs:
<input id="dynamic-input" type="text" aria-label="Search query" />