How to build accessible forms that everyone can complete
Most of an accessible form is native HTML doing its job. Give every field a visible, programmatically associated label (a placeholder is not a label); mark required fields with the required attribute rather than an asterisk alone; use the correct input types and the autocomplete attribute so browsers can help; and group related fields with fieldset and legend. Handle errors properly, which is where most forms fail: the message must identify the problem and suggest a fix, be tied to its field with aria-describedby and aria-invalid, never depend on colour alone, be announced through a live region, and pull focus to the first error on submission. Keep every control keyboard-operable with a visible focus ring and a logical order, never disable the submit button, and never auto-submit on a change. Then test the only way that finds real problems — with a keyboard and a screen reader. Do this and the form works for a blind user, a keyboard user and a low-vision user alike, which is exactly the audience the law now expects you to serve.
Why forms are the surface that matters most
Everywhere else on a site, accessibility is about reading; on a form, it is about doing. Forms are where users sign up, buy, apply and contact you, so when a form is inaccessible it does not merely create a poor experience — it blocks people from completing the essential action, which for a business means lost customers and legal liability (WCAGKit, 2026). Given that one in four US adults lives with a disability, this is not an edge case (UXPin, 2025).
The encouraging part is that the failures cluster in two easy places. WebAIM reports that over 60% of form accessibility issues stem from incorrect labelling and error handling (UXPin, 2025). These are also among the most common failures on the web at large — one industry analysis found 94.8% of websites failing accessibility checks, with form labelling and error identification near the top of the list (beAccessible, 2026). And automated tools alone will not save you: they miss roughly 70% of failures, which is why the manual work later in this guide is not optional (508Blueprint, 2026).
Label every field — and no, a placeholder isn’t a label
Labels are the cornerstone. Every input, select and textarea needs a programmatic label, created with a label element whose for matches the input’s id, or by wrapping the input inside the label (508Blueprint, 2026). Without one, a screen reader announces the field as “edit text” with no context, leaving the user to guess what to type (TestParty, 2025).
The tempting shortcut — using placeholder text as the label — fails on two counts: the placeholder disappears the moment someone starts typing, breaking WCAG 3.3.2, and it is not announced consistently across screen readers, breaking 4.1.2, so a single unlabelled input can fail three criteria at once (508Blueprint, 2026). Keep labels visible, positioned consistently above or beside the field, and concise — “Email” beats “Please enter your email address here” (TestParty, 2025). It also helps to keep the visible label and the accessible name the same, which lets speech-input users say what they see.
Mark required fields, and group related ones
Indicate required fields both ways. Programmatically, use the required attribute so screen readers announce “required” as part of the field; visually, add an asterisk or the word alongside it, with a note near the form explaining what the asterisk means — and never rely on colour to carry that meaning (508Blueprint, 2026). An asterisk alone is a visual convention that assistive technology does not interpret.
Related controls belong in a group. Wrap radio-button sets, checkbox groups and multi-part fields like an address in a fieldset with a legend, so a screen reader announces the group’s purpose before each control inside it (Yale, 2026). One caution: do not nest fieldsets inside each other, since some screen readers handle that unpredictably (reciteme, 2026).
Use the right input types and autocomplete
The type attribute does real accessibility work. Using email, tel, number, url, date and search gives mobile users the correct on-screen keyboard and gives the browser sensible built-in handling (TestParty, 2025). Each still needs its own label — specialised inputs are not self-describing (reciteme, 2026).
The autocomplete attribute is not a nicety, it is a requirement: WCAG Success Criterion 1.3.5 mandates it for fields collecting common personal data, with values like autocomplete="name", "email", "street-address" and "cc-number" (WCAGKit, 2026). It lets browsers and password managers fill fields automatically, cutting the cognitive and motor effort a form demands — a concrete help for users with motor or cognitive disabilities, and lower abandonment for everyone (getAccessGuard, 2026).
Errors are where accessible forms fall apart
Validation is the stage where otherwise-decent forms break. Start with the wording: an error must identify the problem and suggest the fix, so “Please enter a valid email address” rather than “Invalid input” (UXPin, 2025). Then wire it up so assistive technology can perceive it — associate the message with its field using aria-describedby, and set aria-invalid="true" on the field so its state is exposed beyond the visual cue (getAccessGuard, 2026).
Two more pieces complete it. Never signal an error with colour alone — a red border by itself fails WCAG 1.4.1, so pair it with text and an icon that a colourblind or screen-reader user can perceive (WCAGKit, 2026). And announce it: put the message in an aria-live region or use role="alert", then on submission move focus to the first error, or to an error summary at the top of the form that links to each invalid field (getAccessGuard, 2026). That focus move is what tells a keyboard or screen-reader user that something happened, rather than leaving them to wonder why the page reloaded.
Keyboard, focus, and the trap of custom widgets
Every control must be reachable and operable with the keyboard alone, in an order that matches the visual layout — and the simplest way to get there is to use native elements, because input, select, textarea and button are keyboard-accessible by default (getAccessGuard, 2026). Problems begin when a form is rebuilt from div and span elements styled to look like controls, which have no keyboard support until a developer adds it by hand — work that is frequently skipped (Yale, 2026). Keep the DOM order matching the visual order rather than rearranging with CSS, since keyboard users meet fields in source order, and give every control a clearly visible focus ring (WCAGKit, 2026).
Two habits quietly break forms. Graying out the submit button until every field is valid creates confusion, so leave it active and show clear errors on submit instead (WCAGKit, 2026). And do not auto-submit or change context when a value changes — WCAG 3.2.2 treats that as disorienting for keyboard and screen-reader users unless they were warned (getAccessGuard, 2026). This native-first instinct is the same one behind our guide on keyboard accessibility and focus: the built-in control already does the hard part.
High-consequence forms need a safety net
When a submission carries real weight — a payment, a legal agreement, deleting data — WCAG asks for a backstop against mistakes. At least one of three protections must be present: the action is reversible, the submission is checked for errors and the user can correct them, or the user gets to review and confirm the information before it is final (Yale, 2026). A review-and-confirm step is the most common pattern, and it protects everyone, not only users with disabilities.
Test it the only way that works
Automated scanners are worth running — they catch missing labels and invalid ARIA quickly — but they cannot tell you whether a form actually works for a real person, and they miss around 70% of failures (508Blueprint, 2026). The passes that find real problems are manual. Complete the whole form with the keyboard only, confirming every field is reachable in a logical order; navigate it with a screen reader such as NVDA, VoiceOver or TalkBack to hear how labels and errors are announced; and deliberately trigger every validation error to check each one is announced and tied to its field (WCAGKit, 2026). Budgeted honestly, a standard signup or contact form takes about 30 minutes to test this way (508Blueprint, 2026).
Why our forms are accessible by default
Read back over this list and a pattern emerges: nearly every requirement is satisfied by using the native HTML control and letting it do its job. That is not a coincidence, and it is why we build forms the way we do. A native control is keyboard-operable, exposes its role and state to assistive technology, and needs almost no JavaScript — so the accessible choice and the lightweight choice turn out to be the same choice, exactly as they are everywhere else we build. The custom div-based widget that breaks a form is the same kind of heavy, script-driven shortcut we avoid for performance reasons.
It is also worth saying what a form makes obvious: this is precisely the kind of problem an accessibility overlay cannot fix. A widget bolted on at page load cannot supply the label your input never had or rewrite your error handling to announce itself — that has to be built into the form, which is the argument of our guide on why accessibility overlays are a legal trap. Get the form right at the source and you have handled the surface where accessibility, conversions and legal exposure all meet at once — the practical heart of our pillar on whether web accessibility is the law.
Frequently asked
- Can I use placeholder text instead of a label?
- No. Placeholder text disappears the moment someone starts typing, which fails WCAG 3.3.2 (Labels or Instructions), and it is not announced consistently across screen readers, which fails 4.1.2 (Name, Role, Value). An unlabeled input can fail three success criteria at once. Every input, select and textarea needs a visible, programmatically associated label using a real label element tied to the input's id, or the input wrapped inside the label. If space is tight, a floating-label pattern keeps the label visible after typing; a placeholder is at best a supplement, never a replacement.
- How do I make form error messages accessible?
- Four things together. The message must identify the problem and suggest a fix — 'Please enter a valid email address', not 'Invalid input'. It must be programmatically tied to the field with aria-describedby, and the field marked aria-invalid='true'. It must not rely on colour alone — a red border by itself fails WCAG 1.4.1, so add text and an icon. And it must be announced: put the message in an aria-live region or use role='alert', and on submission move focus to the first error or to an error summary at the top of the form.
- Is the autocomplete attribute required for accessibility?
- Yes, for fields that collect common personal information. WCAG Success Criterion 1.3.5 (Identify Input Purpose, Level AA) requires the autocomplete attribute on inputs like name, email, tel, street-address, postal-code and credit-card fields. Beyond compliance, it lets browsers and password managers fill fields automatically, which reduces the cognitive and motor effort a form demands — a real help for users with motor or cognitive disabilities, and a lower abandonment rate for everyone.
- Why are native HTML form controls better for accessibility?
- Because native input, select, textarea and button elements are keyboard-operable and expose their name, role and state to assistive technology by default. The accessibility problems appear when a form is rebuilt from div and span elements styled to look like controls, because those have no keyboard support or screen-reader semantics unless a developer adds them by hand, and that work is frequently skipped or done incompletely. Using the native control, then styling it, gets you accessibility for free — which is also why it needs far less JavaScript.
- How do I test whether my form is accessible?
- Combine automated and manual testing, because automated scanners miss roughly 70% of failures. Run a tool like Axe or WAVE to catch missing labels and invalid ARIA, then do the manual passes that actually matter: complete the entire form using only the keyboard, checking that every field is reachable in a logical order with a visible focus ring; navigate it with a screen reader (NVDA, VoiceOver or TalkBack) to hear how labels and errors are announced; and deliberately trigger every validation error to confirm each is announced and tied to its field. A standard form takes about 30 minutes.