Accessibility Certified – Home

Forms that everyone can complete

Forms are where people buy, book or give up. This guide shows how labels, required fields and error messages need to work for keyboard, screen reader and magnifier users.

Last reviewed: · 6 min read

Every field needs a visible label

Placeholder text is not a label. It disappears as soon as someone types, is often too faint, and not every screen reader reads it. Give every field a visible <label> tied to it with for and id. The screen reader then announces the name, and clicking the label moves focus into the field, which also helps anyone with an unsteady hand.

This covers 1.3.1 Info and Relationships, 3.3.2 Labels or Instructions and 4.1.2 Name, Role, Value. If the visible text differs from the accessible name, voice control users get stuck (2.5.3 Label in Name).

Problem
<input type="email" placeholder="Email">
Better
<label for="email">Email address</label>
<input id="email" type="email" name="email"
  autocomplete="email">

The label stays visible, is tied to the field and enlarges the click area.

Groups, required fields and hints

When fields belong together, such as a set of radio buttons or the parts of an address, wrap them in a <fieldset> with a <legend>. Screen reader users then hear the question when they enter the group.

  • Required fields: say so in text, for example “(required)”, and add the required attribute. A red asterisk on its own is not enough, because colour must not be the only cue (1.4.1 Use of Color).
  • Format hints such as “DD/MM/YYYY” belong before the field, not only in the error message. Connect them with aria-describedby.
  • No time traps: if a session expires, warn people first and let them extend it (2.2.1 Timing Adjustable).
Problem
<p>Payment method *</p>
<input type="radio" name="pay" id="p1">
<label for="p1">Invoice</label>
Better
<fieldset>
  <legend>Payment method (required)</legend>
  <input type="radio" name="pay" id="p1" required>
  <label for="p1">Invoice</label>
  <input type="radio" name="pay" id="p2">
  <label for="p2">Card</label>
</fieldset>

Let the browser fill it in

The autocomplete attribute tells the browser which piece of information a field asks for, so it can offer saved data. 1.3.5 Identify Input Purpose requires this for fields that collect information about the user. It helps people with motor impairments, with reading or memory difficulties, and anyone ordering on a phone.

Use the tokens defined in the HTML standard, such as name, given-name, email, tel, street-address, postal-code or bday. Browsers ignore made-up values.

And do not ask twice: if someone has already entered a delivery address, offer it for billing instead of making them type it again (3.3.7 Redundant Entry).

Error messages that help people fix things

A red border tells a screen reader nothing, and many people with colour vision deficiencies will miss it too. A good error message does three jobs:

  1. It names the field and the problem in text (3.3.1 Error Identification): “Enter your postcode” instead of “Invalid input”.
  2. It suggests a fix when one is known (3.3.3 Error Suggestion): “The postcode should look like D02 X285.”
  3. It is programmatically tied to the field with aria-describedby, plus aria-invalid set to true on the field.

Validate when the field loses focus or on submit, not on every keystroke. With several errors, a summary at the top of the form with links to each field helps; move focus to that summary. A working example lives in our pattern form field with error.

Problem
<input id="pc" class="error">
<span class="red">Error</span>
Better
<label for="pc">Postcode</label>
<input id="pc" name="postcode"
  autocomplete="postal-code"
  aria-invalid="true" aria-describedby="pc-err">
<p id="pc-err">Enter your postcode, for
  example D02 X285.</p>

The message sits next to the field, is read out on focus and tells people what to do.

Before submitting: review, confirm, correct

For orders, contracts, payments and anything with legal consequences, 3.3.4 Error Prevention (Legal, Financial, Data) asks for at least one safeguard: the submission can be reversed, the input is checked and can be corrected, or there is a review step to confirm everything before the final submit. In a shop, that is the order summary with “Change” links back to each step.

Sign-in without a memory test

New in WCAG 2.2, 3.3.8 Accessible Authentication (Minimum) says nobody may be forced to remember, transcribe or solve something to log in unless there is an alternative. In practice:

  • Do not block pasting into password or code fields, so password managers work.
  • Set autocomplete="username", "current-password" and "one-time-code".
  • Avoid splitting one-time codes into separate boxes that refuse pasted input.
  • Offer alternatives such as an email sign-in link or passkeys.

For spam protection without puzzles, see our guide CAPTCHAs and alternatives.

Problem
<input type="password"
  onpaste="return false">
Better
<label for="pw">Password</label>
<input id="pw" type="password"
  autocomplete="current-password">

Checklist

0 of 8 done

Your ticks stay in this browser tab only and are not stored anywhere.

Related WCAG criteria

Tools and patterns for this

Frequently asked questions

Is a placeholder fine if the form is very short?

No. The placeholder vanishes on typing, and anyone who wants to check what a field was for can no longer see it. A small visible label above the field costs very little space.

Should errors appear while people are typing?

Usually not. Messages on every keystroke interrupt screen readers and unsettle people. Validate when the field loses focus or on submit, then move focus deliberately.

Do I need aria-required if I use required?

Generally not. The HTML required attribute is passed on to assistive technology. What matters as well is the visible hint in text.

Sources

How does your website do?

The free check tests your home page in two minutes. The audit decides all 55 criteria, by a person.

Free checkSee pricing

More guides