Accessibility
Accessible forms: what everyone must be able to fill in
How labels, field types, autocomplete and error messages make a form usable for everyone, what the CAPTCHA has to do with it and how to check your own in five minutes.
12 min read
By Timo Wessels Published
A form is accessible when anyone can fill it in and send it without help: with a screen reader, with the keyboard alone, on a phone or with a learning difficulty. It takes little. Every field has a visible label that is linked to it in the code, groups have a heading, and errors are reported as text next to the field and say what to do. Add the right field type and autocomplete, which make typing easier or spare it altogether. Almost all of it is standard HTML and costs next to nothing in a new build.
The label: for and id
A form consists of the <form> element, the fields, their labels and the submit button. The decisive point is the link between label and field. The W3C forms tutorial puts it briefly: the for attribute of the <label> must exactly match the id of the field.
<label for="email">Email address</label>
<input type="email" id="email" name="email" autocomplete="email">
Only this link turns two elements that happen to sit next to each other into a pair that a screen reader also recognises as belonging together. On the side, the label becomes clickable and so enlarges the area that hits the field. You cannot see the difference: a field with some text above it looks exactly like a field with a linked label. It only becomes audible with a screen reader.
The link falls under criterion 1.3.1 "Info and Relationships", level A; having a label at all falls under 3.3.2 "Labels or Instructions", also level A. Anyone building their own controls from div and span instead of standard fields has to supply name, role and state themselves (4.1.2, level A). Regular HTML fields do that on their own, one more reason to stick with them.
A placeholder is not a label
The most common mistake looks the tidiest: no label above the field, just grey text inside it. The W3C tutorial names three problems:
- It disappears as soon as someone starts typing. Anyone returning after a distraction sees a half-filled field with no hint of what belonged in it.
- It is too faint. Browsers' default styling does not reach the WCAG minimum contrast.
- Assistive technologies do not treat it as a label.
Placeholders may stay, as an example of a format. They are no replacement for the label.
The field type decides the phone keyboard
This is the point with the greatest everyday benefit for the least effort. The type attribute controls which on-screen keyboard a mobile browser shows, and most types check the input as well:
| Field | type |
What the user gets |
|---|---|---|
| Phone number | tel |
telephone keypad with digits, star and hash |
email |
keyboard with @, format check |
|
| Website | url |
keyboard with an easy-to-reach /, format check |
| Search | search |
return key often labelled "Search" |
| Quantity | number |
numeric keyboard |
| Date | date |
date picker, varying by browser and system |
A phone field with type="text" means: the user gets a letter keyboard, looks for the key that switches to digits and types on, on every form. type="tel", by the way, checks no format, because phone numbers differ too much around the world. That is as it should be.
Careful with number: MDN advises using it only for real quantities. Postcodes or card numbers consist of digits but are not numbers. For those, use type="text" with inputmode="numeric".
autocomplete spares the typing altogether
The field type says what kind of data is expected. autocomplete says what the field is for: given-name for the first name, family-name for the surname, email, tel, street-address, postal-code. new-password tells the password manager that a new password is being created here, current-password that the stored one should be filled in.
Criterion 1.3.5 "Identify Input Purpose", level AA, requires exactly this for every field that collects information about the person. The W3C names as beneficiaries people with memory and language difficulties, for whom the browser fills in the details, and people with motor impairments, who have to type less. For everyone else it saves seconds per field. Important: only the defined values count. An invented value does not meet the criterion.
Required fields: required and a word
Whether a field is required is a business decision: does the enquiry really need a phone number, or is the field only there because it always was?
Once decided, it belongs in the HTML. The required attribute prevents submission while the field is empty and tells assistive technologies that it is required. MDN recommends it for all regular fields. aria-required="true" passes the same information only to assistive technologies and checks nothing. It is meant for custom controls that are not HTML fields.
A red asterisk or a red border alone is not enough, because colour does not carry the information for everyone. MDN names text or an icon as the usual marker, such as "(required)" in the label, or an asterisk with an explanation above the form.
Group what belongs together
For radio buttons a group label is necessary. Three options without an overarching question are three unconnected words. The W3C tutorial says: radio button groups always belong in a <fieldset>, and checkbox groups too. <legend> gives the group its heading.
<fieldset>
<legend>How should we reach you?</legend>
<input type="radio" id="k-mail" name="kontakt" value="mail">
<label for="k-mail">By email</label>
<input type="radio" id="k-tel" name="kontakt" value="tel">
<label for="k-tel">By phone</label>
</fieldset>
Screen readers handle the legend differently: depending on the setting they read it with every field, once, or rarely not at all. That is why the W3C advises keeping the legend short and wording each label so it makes sense without the legend. The same device organises long forms: personal details in one block, contact details in the next.
Error messages that help
"Error" is not a message. The criteria ask for three things:
- The error is stated in text (3.3.1, level A). A red border may be there as well, but it does not replace the text.
- The message says what to do when a correction is known (3.3.3, level AA). "Enter the date as DD.MM.YYYY" rather than "Invalid input". If it is clear what was meant, the message may suggest it, in the style of "Did you mean …?".
- The message is linked to the field. W3C technique ARIA21 sets
aria-invalid="true"on the field and connects it to the message text viaaria-describedby. The screen reader then reads the message as soon as the field receives focus.
The W3C tutorial also recommends listing all errors above the form after submission and setting focus to the first faulty field. For some fields it makes sense to check when the user leaves the field rather than only on submission. The success message afterwards belongs in an area with role="status", so that a screen reader announces it without focus having to move (4.1.3, level AA).
Being forgiving beats reporting well. The W3C advises accepting as many notations as possible: phone numbers with spaces, slashes or +49. And it warns against number-only fields for postcodes, because in many countries they contain letters. A form that accepts such input and tidies it up itself produces no error at all. Checking in the browser does not replace checking on the server, by the way: it can be bypassed.
Help before the error happens
If a field expects a particular format, say so: as text below the field, linked via aria-describedby. That way the explanation is read out after the label instead of merely sitting there. For file uploads it means naming the allowed formats and the maximum size before someone uploads a file that is too large.
The W3C urges moderation: too much instruction harms as much as too little. One hint per field, where it is needed, is enough.
Forms with consequences: let people check
Criterion 3.3.4, level AA, applies to forms that create a legal commitment or a payment, change or delete stored user data, or submit test answers. At least one of the following must then hold:
- Reversible: the submission can be undone.
- Checked: the input is checked for errors and the user can correct them.
- Confirmed: before the final submission there is an overview to review and correct.
A contact form does not require this. An order, a paid booking or a cancellation does.
The CAPTCHA at the end
Two topics meet here at an awkward spot.
Accessibility: in its note on the inaccessibility of CAPTCHAs, the W3C states that distorted characters cannot be solved by blind people, because the screen reader cannot read the image. The audio alternative is distorted too and overlaid with noise, and it puts a far greater load on all users than normal speech. Anyone placing such a CAPTCHA in front of their contact form loses prospects without noticing.
Data protection: Austria's Federal Administrative Court ruled on 13 September 2024 (W298 2274626-1/8E) that Google reCAPTCHA is not technically necessary for running a website and therefore needs consent. As the ruling rests on the European cookie directive, it is considered relevant for Germany too. In practice this is a dilemma: load reCAPTCHA only after consent, and there is no protection at all for everyone who declines the cookie banner.
As an alternative that sets the user no puzzle, the W3C names among others the honeypot: an invisible field that only bots fill in. It bothers nobody, and according to the W3C it works well enough that several content management systems offer it. Whether another CAPTCHA service may be used without consent is a question for data protection advice.
How to check it yourself
Five tests, none needs a tool:
- The click test. Click the label text above a field. If the cursor jumps into the field, the link is there. If nothing happens, it is missing. This works on any form, including other people's.
- The keyboard test. Put the mouse aside. Tab through the form, fill in every field, submit. Can you reach everything? Can you see where you are at each step?
- The error test. Submit the form wrongly on purpose: a required field empty, an email without
@. Is the message there as text next to the field? Does it say what to do? Does focus land on the error? - The phone test. On your phone, tap into each field in turn. Does the phone field bring up the keypad, the email field a keyboard with
@? If the same letter keyboard appears everywhere, the field types are missing. - The autofill test. Click into the name field. Does the browser offer a suggestion? If not,
autocompleteis probably missing.
For a closer look, add a screen reader. NVDA is free for Windows.
What to do
- A visible label on every field, linked via
forandid. Placeholders only as a format example. - Set field types:
tel,email,url,date.numberonly for real quantities. autocompleteon every field with personal details.- Required fields with
required, and marked in text, not only with colour. - Radio buttons and checkbox groups in a
<fieldset>with a<legend>. - Error messages as full sentences next to the field, with
aria-describedbyandaria-invalid="true", and a success message withrole="status". - Write format hints next to the field and link them as well.
- Replace the visual CAPTCHA, in the simplest case with a honeypot.
- And the point that brings the most: fewer fields. Every field you drop needs no label and no check, and nobody has to fill it in.
What the law requires
Since 28 June 2025, Germany's Accessibility Strengthening Act (Barrierefreiheitsstärkungsgesetz, BFSG) applies to services for consumers, including e-commerce. Order, booking and sign-up forms are at the centre of it, because that is where the actual transaction takes place. Micro-enterprises with fewer than ten employees and an annual turnover or balance sheet total of at most 2 million euros are partly exempt. The benchmark is the European standard EN 301 549, which according to the federal government makes WCAG 2.1 levels A and AA mandatory. All criteria in this article belong to that core. Whether your business is affected is a question for legal advice, not for a technical check. Either way: in a new build these measures cost almost nothing, afterwards considerably more.
Sources
- W3C WAI, Forms Tutorial: Labeling Controls —
forandid, larger click area: w3.org - W3C WAI, Forms Tutorial: Form Instructions — placeholders,
aria-describedbyfor hints: w3.org - W3C WAI, Forms Tutorial: Grouping Controls —
fieldsetandlegend, screen reader behaviour: w3.org - W3C WAI, Forms Tutorial: Validating Input — forgiving validation, postcodes, server-side checks: w3.org
- W3C WAI, Forms Tutorial: User Notifications — error list, focus on the first faulty field, checking on leaving a field: w3.org
- W3C, Understanding WCAG 2.2 — 1.3.1 Info and Relationships, techniques H44 and H71: w3.org
- W3C, Understanding WCAG 2.2 — 1.3.5 Identify Input Purpose: w3.org
- W3C, Understanding WCAG 2.2 — 3.3.1 Error Identification: w3.org
- W3C, Understanding WCAG 2.2 — 3.3.2 Labels or Instructions, too much instruction harms: w3.org
- W3C, Understanding WCAG 2.2 — 3.3.3 Error Suggestion: w3.org
- W3C, Understanding WCAG 2.2 — 3.3.4 Error Prevention, three ways: w3.org
- W3C, Understanding WCAG 2.2 — 4.1.2 Name, Role, Value: w3.org
- W3C, Understanding WCAG 2.2 — 4.1.3 Status Messages,
role="status": w3.org - W3C, Technique ARIA21 —
aria-invalidwitharia-describedby: w3.org - W3C, Inaccessibility of CAPTCHA — visual and audio CAPTCHAs, honeypot: w3.org
- MDN,
<input type="tel">— telephone keypad, no format check: developer.mozilla.org - MDN,
<input type="number">— only for real quantities, not for postcodes: developer.mozilla.org - MDN,
<input type="date">— date picker varying by browser: developer.mozilla.org - MDN,
inputmode— on-screen keyboards foremail,url,search: developer.mozilla.org - MDN,
autocomplete— values and the link to 1.3.5: developer.mozilla.org - MDN,
aria-required—requiredtakes precedence, marking not by colour alone: developer.mozilla.org - IT-Recht Kanzlei, Austrian Federal Administrative Court on Google reCAPTCHA — 13.09.2024, W298 2274626-1/8E, consent required: it-recht-kanzlei.de
- NV Access, About NVDA — free screen reader for Windows: nvaccess.org
- Federal accessibility portal (Portal Barrierefreiheit des Bundes) — Accessibility Strengthening Act, in force from 28.06.2025, micro-enterprises: barrierefreiheit-dienstekonsolidierung.bund.de
- Federal accessibility portal — WCAG 2.1 and EN 301 549, levels A and AA: barrierefreiheit-dienstekonsolidierung.bund.de