Accessibility
Why forms are harder than they look
Almost every website has one.
11 min read
By Timo Wessels Published
Almost every website has one. Name, email, message, a button. That looks like half an hour of work.
And for what you can see, that is true. Except that a form is the only place on your website where a visitor does something instead of reading. Everything else they can skim. Here they have to hit, type, understand why an entry is rejected — and in the end, what they wrote actually has to reach you.
Those are four places where something can go wrong, and none of them shows on the finished form.
A form is just HTML
That sounds trivial and is the starting point.
A form has exactly one fixed rule: it sits in a form element. Everything inside is free. You can put the fields into containers or into a list. On screen both look identical — the choice changes nothing about how it is displayed.
And that is exactly why the choice should be made consciously. When two options look the same, but one of them also describes what the parts have to do with each other, there is no reason for the other.
It is the same argument as with lists and tables: the right markup costs nothing extra and carries meaning a rebuilt imitation does not have.
The label you do not see
Every field needs a label that is technically connected to the field — not just a piece of text next to it.
The difference is invisible. A field with a connected label and one with loose text beside it look exactly the same. But there is a test that takes ten seconds:
Click on the label text, not on the field.
If the cursor jumps into the field, the connection is there. If nothing happens, it is not.
With a checkbox the difference is even clearer: with the connection you can click on the word and the box ticks itself. Without it you have to hit the box itself — a target of a few millimetres, on a phone, with your thumb.
And for someone who has the page read out to them, the connection is the only way to find out what a field is for at all. Without it the screen reader says “edit text” and nothing else.
There are two ways to make the connection: the label refers to the field's identifier, or the label wraps around the field. Both are correct.
The grey text in the field is not a label
The most widespread mistake, and it comes from a design wish: the form looks tidier when the label sits in the field rather than above it.
The problem is simple: that text disappears as soon as someone starts typing.
Anyone who pauses at the third field to remember what they were about to enter has no way of checking any more. Anyone who wants to check whether they wrote into the right field cannot either. And anyone who submits the form and gets an error back faces fields without any label at all.
The accessibility rules are unambiguous here: placeholder text may never be the only label. It may be there in addition, as an example of the expected format. As a replacement, no.
Groups need a heading
Most obviously with choices of which only one applies.
When three options stand below each other, each has its own label. What is missing is the question they belong to. On screen the question stands above them as a heading, and the eye makes the connection.
Someone who has the page read out hears only the answers. The question is visually there and technically not connected.
For this there is an element that groups fields together, and a second one that gives the group a heading. Together they say: these fields belong together, and this is the question.
Incidentally, this also makes long forms more readable — contact details, request, consents as three visible blocks instead of a chain of twenty fields.
The right field type — and what it does not do
An input field can have different types: text, email, phone number, address, number, date. The difference has two visible effects.
The first is the phone. A field of type email brings a keyboard with the @ sign. A phone field brings the number pad. A text field brings the normal keyboard, and the visitor looks for the @ themselves. That is no small thing — it is the difference between two and six moves, on every field.
The second is a first check in the browser, before anything is sent.
And here comes the part you need to know: this check is weaker than it looks.
An email field accepts an address without a dot after the @, because such addresses really do occur in company networks. A phone field does not check the input at all, because phone numbers are structured too differently internationally for a general rule to work.
So the field type is a convenience feature with a small checking effect. It is not a control.
Autofill
Browsers can fill in name, address and phone number themselves — but only if the field says what it is for. Without that declaration the browser guesses, and mostly it does not guess.
It is one of the few measures that harms nobody and clearly helps several groups: people who have trouble remembering things do not have to look them up. People with motor impairments save every single keystroke. And everyone else is finished faster.
It is a requirement of its own in the accessibility rules, and it is one line per field.
Checking happens in two places, for two reasons
This is the point where self-built forms are most often incomplete.
In the browser, checking is for the visitor. They should see at once that a detail is missing, instead of submitting, waiting and getting the answer back. That is a convenience feature.
On the server, checking is for you. And that is not convenience but the only check that counts. There are three reasons for it:
First, there are checks only the server can do. Whether an appointment is still free, whether a customer number exists, whether a quantity is available — that needs the data, and the data is not in the browser.
Second, the check in the browser runs on someone else's computer. It is delivered together with the page. Anyone who wants to can switch it off and submit anyway. A check the sender controls is no check.
Third, people make mistakes. A checking rule in the browser can be written wrongly and therefore let everything through. If nobody notices, the wrong data still ends up with you.
If your form comes from a plugin, the plugin normally does the server check too. If someone built a form by hand because it was supposed to look nicer, that is exactly the place to look.
What a form fundamentally cannot check
Whether an email address actually exists.
That cannot be established while the form is being filled in, with any method. The only proof is to send a message to that address and wait for someone to click a link in it. That is exactly why sign-ups all over the world work this way.
So anyone building a list from a form should know: the addresses in it are unconfirmed until someone has responded.
And then the message has to arrive
Almost every guide stops here, and this is where the part begins that goes wrong most often in practice.
A form is not finished when it can be submitted. It is finished when the message is in your inbox.
Between the two lies a chain: your website hands the message to a sending route. The sending route hands it to the recipient's mail server. And that server decides whether to accept it, reject it or put it in the spam folder — on the basis of records that are not on your website but at your domain.
That explains an observation many site owners make and cannot place: the form says “message sent”, and still nothing arrives. Both are true at the same time. The website handed it over, and after that something happened it knows nothing about.
That is a topic of its own and has an article of its own. For here the consequence is enough: A form only counts as checked once you have filled it in from outside and received the mail. Not while logged in, not with your own address as the sender, but the way a stranger would.
What you check yourself in ten minutes
You do not need a tool for this.
Click on the labels. Not on the fields — on the text next to them. Does the cursor jump in?
Go through with the Tab key. Do you reach every field? Do you see at every step where you are? Do you get to the submit button at the end?
Open the form on your phone. Do you get the keyboard with the @ on the email field? The digits on the phone field?
Submit it empty. What happens? Does it say anywhere which field is missing — and does it say so at the field or only at the top as a general notice?
Type something wrong. Do you understand the error message? Or is there a technical phrase nobody outside development reads?
And then fill it in properly once, from outside, with a foreign address. Does the mail arrive? How fast? And is it in the inbox or in spam?
The unspectacular core
Nothing about a form is difficult. Every single point here is one line of markup or one setting in the plugin.
They still regularly fail, because a form counts as finished as soon as it looks nice and can be submitted. That is the state most forms are in — and in which they are harder for half of all visitors than they need to be.
Sources
- Udemy, Web Forms — Build and Master HTML Web Forms, section 4 — that the structure of a form is free and the choice between containers and lists does not change the display; that a label achieves nothing visually but does make a click on its text select the associated control; that there are two ways to connect label and field, namely through a reference to the identifier or by wrapping; that a grouping element together with a heading element gathers fields with the same purpose and makes long forms more understandable.
- Udemy, Web Forms, section 6 — that a field of type email accepts an address of the form characters-at-characters as valid, because addresses from company networks are allowed; that it is fundamentally impossible to establish from the browser side whether an address exists, and that the usual proof is to send a message with a confirmation link; that a field of type phone number performs no format check, because phone numbers are structured too differently internationally.
- Udemy, Web Forms, section 10 — that the check in the browser is a first control and a convenience feature, because the visitor sees an error at once instead of after a trip to the server and back; and the three reasons for checking on the server: that some checks require a data set only the server has; that the check in the browser is delivered with the page and can therefore be bypassed; and that a wrongly written checking rule lets everything through unnoticed.
- Atlas,
accessibility/criteria/3-3-2-labels-or-instructions.md— that every input field needs a visible label, that fields with format requirements also get a note on the expected format, and that placeholder text must never serve as the only label, because it disappears on input. The requirement is at the basic level. - Atlas,
accessibility/criteria/1-3-5-identify-input-purpose.md— that the purpose of a field collecting personal details has to be declared machine-readably so that autofill works; that people with cognitive impairments benefit from it and people with motor impairments save considerable effort. The requirement is at the middle level. - Own audit practice — the order of the self-check, the click test on the label text, the check on the phone for the right keyboard, and the rule to only consider a form checked once it has been filled in from outside with a foreign address and the message has arrived.
- Reference instead of repetition — the chain from submitting to the inbox is only named here. Why a message is sorted out on the way and which records at the domain decide about it is in the article on mail that lands in spam.