The problem
Forms are where conversions happen—sign-ups, checkouts, contact requests—so an unlabeled form is a direct loss of business and a top ADA-lawsuit target. Without a programmatic label, a screen reader announces an input as just “edit text,” giving no hint whether it wants an email, a password, or a phone number. Placeholder-only forms look fine to sighted users but are an invisible wall for assistive-technology users and people with cognitive disabilities.
The fix
<input type="email" placeholder="Email">
<input type="password" placeholder="Password">
<button>Submit</button><label for="email">Email address</label>
<input id="email" type="email" autocomplete="email">
<label for="password">Password</label>
<input id="password" type="password" autocomplete="current-password">
<button type="submit">Sign in</button>Step by step
- Add a
<label>element with a for attribute matching the input's id. - Or use
aria-label="Email address"on the input directly. - Do not use placeholder as the only label — it disappears when the user types.
- Group related inputs with
<fieldset>and<legend>(e.g., radio button groups).
Common mistakes
- Using placeholder text as the only label (it disappears on input and often fails contrast).
- Adding a
<label>but forgetting the for/id association. - Labeling a group of radios or checkboxes without
<fieldset>/<legend>. - Hiding labels with display:none, which also hides them from screen readers.
How to test for it
- Click each field’s label—focus should move to the input, which proves the association.
- Tab through the form with a screen reader and confirm each field announces its purpose.
- Run an automated scan for inputs missing an accessible name.
In your framework
// React — associate label and input
<label htmlFor="email">Email</label>
<input id="email" type="email" />Questions
Can I use placeholder instead of a label?
No. Placeholder text fails as the only label — it vanishes when typing, isn't announced on focus in all screen readers, and usually fails contrast.
What about icon-only buttons?
Add aria-label to the button: <button aria-label="Close dialog"><svg ...></svg></button>
Find it on your site.
Scan a page and see every place this issue appears, with the element and the fix.
Scan your site