The short answer

Give every field a visible label tied to it with for and id, mark required fields in text, group related options with fieldset and legend, show errors in words next to the field and in a summary, use the right input types and autocomplete, and make sure the whole form works with a keyboard.

Key takeaways

  • Every input needs a real, visible label, not just a placeholder.
  • Say "required" in text, not only with a red star.
  • Error messages explain how to fix the problem.
  • Use autocomplete so people do not type the same details twice.
  • Do not rely on drag-and-drop or puzzles to prove someone is human.

Missing form labels were found on 51% of the top one million home pages in the WebAIM Million 2026 report. Without a label, a screen reader just says “edit text”, and the person has to guess. Every guess is a chance to lose a sale or a lead.

The step-by-step fix

  1. Label every field

    Use <label for="email">Email</label> with <input id="email">. Clicking the label should put the cursor in the field.

  2. Mark required fields clearly

    Write “(required)” in the label, or explain the asterisk at the top of the form. Add the required attribute.

  3. Wrap radio buttons and checkbox groups in a fieldset with a legend, such as “Preferred contact method”.

  4. Use the right types

    type=”email”, type=”tel” and inputmode bring up the right phone keyboard. Add autocomplete=”email”, “name”, “postal-code” and so on.

  5. Write helpful errors

    Show the error next to the field in text (“Enter a date like 2026-03-15”), link to it from a summary at the top, and connect it with aria-describedby.

  6. Test it

    Fill the form with only a keyboard, then with a screen reader, then make a mistake on purpose and see if the message helps.

Placeholders are not labels

Placeholder text disappears as soon as someone types, is often low contrast, and is not read reliably by all assistive tech. Keep a visible label above the field. Use the placeholder only for an example format, if at all.

Errors that help

“Invalid input” helps no one. Say what went wrong and how to fix it: “Phone number must be 10 digits, like 514 555 0199.” Do not use colour alone; add an icon or the word “Error”. When the form fails, move focus to a summary at the top that lists each problem as a link to the field.

New WCAG 2.2 rules for forms

  • Redundant Entry (3.3.7): do not make people type the same information twice in one process. Offer “same as billing address”.
  • Accessible Authentication (3.3.8): do not force people to solve a puzzle or remember a code to log in. Allow password managers and paste.
  • Target Size (2.5.8): buttons and checkboxes should be at least 24 by 24 pixels, or spaced out so they are easy to tap.

Read the full list in WCAG 2.2 explained in plain words.

Contact form plugins

Most popular WordPress form plugins can output accessible markup, but settings matter. Turn on labels (not placeholder-only), choose inline error messages, and avoid image CAPTCHAs. After you change settings, run a scan: Accessible Nord flags inputs without labels on every page it checks.

Sources

  1. The WebAIM Million, 2026 report
  2. W3C WAI: Forms tutorial
  3. Understanding WCAG 2.2: Redundant Entry (3.3.7)
  4. Understanding WCAG 2.2: Accessible Authentication (Minimum) (3.3.8)

Last reviewed .

Frequently asked questions

Can I hide labels visually?

You can use a visually hidden label for simple cases like a single search box with a clear search button. For most forms, visible labels help everyone, including people with memory or attention difficulties.

Is a CAPTCHA accessible?

Image and puzzle CAPTCHAs block many people. Use invisible checks like a honeypot field, rate limits, or a modern challenge that does not ask people to solve a task.

Should I validate as people type?

Validate when a person leaves a field or submits, not on every key press, which can be noisy for screen reader users.

This guide is general information, not legal advice. For your specific obligations, check with a lawyer or your regulator.