Accessibility

How to Build Accessible Forms

Forms are where accessibility most often breaks. Here is how to label, group, validate and manage focus so everyone can complete them, with a checklist.

StackOptic Research Team21 May 20269 min read
How to build accessible forms with labels, grouping and clear error handling

Forms are where accessibility most often breaks — and where broken accessibility hurts most, because forms are how people sign up, log in, pay, and get help. Building an accessible form comes down to a handful of disciplines: give every control a real, associated label (not a placeholder); group related controls with <fieldset> and <legend>; handle required fields and errors in clear text, wired up with aria-describedby and aria-invalid, with focus moved to the problem; use the right input types and autocomplete so the correct keyboard appears and browsers can autofill; and make the whole thing keyboard operable with visible focus. Get these right and everyone — screen-reader users, keyboard users, people with cognitive or motor disabilities, and everyone else — can complete your forms. This guide covers each, with a field-by-field reference table and a checklist.

It applies the standard from what WCAG is and the difference between A, AA and AAA and leans on the labelling techniques from what ARIA is and when to use it.

Why forms deserve special attention

A form is a conversation: the site asks, the user answers. For that conversation to work for everyone, each question must be perceivable (the user knows what is being asked), the controls must be operable (they can provide an answer with whatever input they use), the process must be understandable (they know what is required and what went wrong), and it must be robust (it works with their assistive technology). Those are the four POUR principles, and a form exercises all of them at once — which is exactly why forms are a frequent point of failure in accessibility testing. A missing label, a colour-only error, or a keyboard trap in a date picker can stop a user dead at the most consequential moment on your site.

Labels: the foundation

The single most important rule of accessible forms is that every control must have a label that is programmatically associated with it. The standard way is an explicit association:

  • Give the input an id, and the <label> a for attribute with the same value: <label for="email">Email</label> and <input id="email" type="email">. Now a screen reader announces "Email, edit text" when the field is focused, and clicking the label moves focus to the field (a bonus for everyone, especially people with motor difficulties, because it enlarges the target).

A few label rules matter:

  • Placeholders are not labels. Placeholder text vanishes the moment someone types, frequently has weak contrast, and is not reliably treated as the field's name by assistive technology. Use a real, persistent label, and reserve placeholders for optional hints like an example format. Relying on placeholders alone is one of the most common form-accessibility failures.
  • Do not hide labels to look "clean". If a design calls for no visible label, you still need an accessible name — but a visible label is almost always better for everyone, including users with cognitive disabilities who benefit from a persistent prompt. If you truly must omit the visible text, use aria-label or visually hidden label text rather than nothing.
  • Mark required fields in text, not just an asterisk colour. A red asterisk alone relies on colour and is ambiguous; pair it with aria-required="true" (or the native required attribute) and make the meaning of the asterisk clear in text near the form.

Grouping related controls

Some questions are made of several controls that only make sense together. A set of radio buttons ("How should we contact you? Email / Phone / Post") needs more than three individual labels — the user must also hear the question that binds them. That is what <fieldset> and <legend> are for:

  • Wrap the related controls in a <fieldset>, and put the group's question in a <legend>. Screen readers announce the legend together with each control, so the user hears "Preferred contact method, Email, radio button 1 of 3."

Use this grouping for radio-button and checkbox sets, and for logical sections of a longer form such as a shipping address or billing details, where the legend ("Shipping address") gives context to the fields inside. Grouping is one of those structures that screen-reader users rely on and sighted users never notice — a hallmark of good accessibility. (Where a native <fieldset>/<legend> is impractical, an ARIA group with aria-labelledby can stand in, following the guidance in what ARIA is and when to use it.)

Required fields, validation and error handling

Error handling is where forms most often fail disabled users, and where good design pays off most. The principles:

Tell people what is required, up front and in text. Use the native required attribute (and/or aria-required="true") so assistive technology announces a field as mandatory, and make any visual convention (like an asterisk) explained in words.

Never signal an error by colour alone. A field that turns red with no text leaves colour-blind and screen-reader users unaware anything is wrong — a violation of WCAG's "use of colour" rule. Always accompany an error with a text message.

Write specific, helpful messages. "Invalid input" tells the user nothing. "Enter a valid email address, for example name@example.com" tells them exactly how to recover. Good error text is concrete about what is wrong and how to fix it.

Wire the message to the field. Put the error text in an element with an id, and reference it from the input with aria-describedby="that-id", so a screen reader reads the error when the field is focused. Mark the field itself with aria-invalid="true" so its error state is announced.

Move focus to the problem. On submit, if there are errors, move keyboard focus either to the first invalid field or to an error summary at the top of the form that lists the problems as links to each field. This takes keyboard and screen-reader users straight to what needs fixing instead of leaving them to hunt.

Announce errors that appear dynamically. If validation happens live or the summary appears without a page reload, put it in a live region (aria-live="assertive" or role="alert") so screen-reader users are told. Live regions are covered in what ARIA is and when to use it.

Do not rely on time limits. If a form session can time out, warn the user and let them extend it; abrupt time limits are a WCAG concern and disproportionately affect people who type slowly.

Input types, autocomplete and the right keyboard

Modern HTML input types do real accessibility work for free:

  • Use the correct type. type="email", type="tel", type="number", type="url", type="date" each prompt mobile browsers to show the most suitable on-screen keyboard (an @ sign for email, a numeric pad for tel) and let browsers offer format validation. This reduces effort and errors for everyone, and especially for people who find typing laborious.
  • Set autocomplete. Attributes like autocomplete="email", autocomplete="name", autocomplete="street-address", autocomplete="tel" let browsers and assistive tools autofill known values. This is not just convenience: WCAG 2.1's Identify Input Purpose criterion expects common fields to declare their purpose this way, which is a significant help to users with cognitive and motor disabilities.
  • Use native controls where you can. A native <select>, <input type="checkbox"> or <input type="date"> brings keyboard support and semantics out of the box — the native-first principle from what ARIA is and when to use it. Reach for a custom widget only when no native control fits, and then follow the WAI-ARIA patterns and manage focus and keys yourself.

Keyboard operability and focus

A form must be fully operable with the keyboard alone — a WCAG Level A requirement and a frequent failure point. Confirm that:

  • Every control is reachable and operable with Tab, and activated with the expected keys (Space toggles checkboxes, arrow keys move within a radio group, Enter submits).
  • The focus order is logical, following the visual order of the fields.
  • The focus indicator is always visible, so keyboard users can see which field they are in (never remove the outline without replacing it).
  • Custom widgets (date pickers, comboboxes, custom selects) are not keyboard traps and follow expected key behaviour.

All of this is covered in depth in how to make a website keyboard accessible, and the keyboard pass there is the fastest way to catch form problems.

Element-to-requirement reference

This table summarises what each part of a form needs:

Element / situationAccessibility requirement
Text inputAssociated <label for>; correct type; autocomplete where applicable
Email / phone / numberSpecific type (email/tel/number) for the right keyboard and validation
Required fieldrequired and/or aria-required="true"; requirement stated in text, not colour
Radio-button group<fieldset> + <legend> for the question; a <label> per option
Checkbox group<fieldset> + <legend>; each checkbox individually labelled
Single checkboxAssociated <label> describing what it toggles
Select / dropdownNative <select> where possible; associated label
Help / hint textLinked with aria-describedby so it is announced
Error messageIn text; aria-invalid="true" on the field; aria-describedby to the message; focus moved to it
Address / section block<fieldset> + <legend> to give the section context
Submit buttonNative <button type="submit"> with clear text ("Create account", not "Submit")

An accessible-form checklist

  • Every control has a visible, programmatically associated label.
  • No field relies on placeholder text as its label.
  • Related controls (radios, checkboxes, address) are grouped with <fieldset>/<legend>.
  • Required fields are marked in text and exposed to assistive technology.
  • Correct input type is used; autocomplete is set on common fields.
  • Errors are shown in specific text, with aria-invalid and aria-describedby, never colour alone.
  • Focus moves to the first error or an error summary on submit.
  • Dynamic validation messages are announced via a live region.
  • The whole form is keyboard operable, with logical order and visible focus.
  • Tested with a keyboard and a screen reader, end to end.

Common form-accessibility mistakes

The repeat offenders are worth naming: placeholder-as-label, unlabelled controls that announce as "edit text", colour-only error states, vague error messages ("invalid"), no focus movement to errors so users cannot find them, custom date pickers and dropdowns that trap the keyboard or ignore expected keys, removed focus outlines, and missing autocomplete that makes routine fields needlessly hard. Each is straightforward to fix, and most are avoided by using native elements with proper labels — then verified by actually completing the form with a keyboard and a screen reader, as in how to check if a website is accessible.

The bottom line

Accessible forms come down to clarity and association: label every control (and never lean on placeholders), group related controls with <fieldset> and <legend>, handle errors in specific text wired up with aria-invalid and aria-describedby and reinforced by moving focus to the problem, use the right input types and autocomplete so the correct keyboard appears and browsers can autofill, and ensure the whole form is keyboard operable with visible focus. Because forms exercise all four POUR principles and gate your most important user journeys, they repay this care more than almost anything else on a site. For the standard behind it, see what WCAG is and the difference between A, AA and AAA; to verify your work, how to run an accessibility audit.

Want to check whether your forms and the rest of your site pass a WCAG accessibility check, alongside SEO and performance? Analyse any URL with StackOptic — one report, free, no sign-up.

Frequently asked questions

Why do form fields need labels?

A label tells every user what a field is for, and when it is programmatically associated with the input — typically a <label for='id'> matching the input's id — a screen reader announces that label when the field receives focus. Without it, the field may be announced only as 'edit text', leaving blind users guessing what to type. Associated labels also enlarge the clickable area, which helps people with motor difficulties, so labels benefit everyone, not just screen-reader users.

Can I use placeholder text instead of a label?

No. Placeholder text is not a substitute for a label. It disappears as soon as the user starts typing, so they lose the prompt; it often has poor colour contrast; and it is not reliably announced as the field's name by assistive technology. Always provide a real, persistent label associated with the input, and use placeholders only for supplementary hints, such as an example format, if at all. Relying on placeholders alone is a common accessibility failure.

How should form errors be handled accessibly?

Communicate errors in text, never by colour alone. Identify which field is wrong and say specifically how to fix it ('Enter a valid email address such as name@example.com'), not just 'invalid input'. Associate the message with its field using aria-describedby, mark the field with aria-invalid='true', and move keyboard focus to the first error or to a summary so the user is taken straight to the problem. Announcing errors via a live region helps screen-reader users notice them.

What are fieldset and legend for?

The <fieldset> element groups related form controls, and the <legend> gives that group a caption. They are essential when individual labels are not enough on their own — most importantly for a set of radio buttons or checkboxes, where the legend supplies the question ('Preferred contact method') and each control has its own label ('Email', 'Phone'). Screen readers announce the legend with the group, so the user understands what the choices relate to. They are also useful for sections like a shipping address.

How do input types and autocomplete help accessibility?

Using the correct input type (email, tel, number, date, url) tells mobile browsers to show the most suitable on-screen keyboard and lets browsers validate the format, which reduces errors for everyone. The autocomplete attribute (for example autocomplete='email' or 'street-address') lets browsers and assistive tools fill in known values, which is a WCAG 2.1 requirement (Identify Input Purpose) and a major help to people with cognitive or motor disabilities who find typing laborious.

Analyse any website with StackOptic

Get the full technology stack, performance, security and SEO report in seconds — free.

Analyse a website

Related articles