Web form design best practices: labels, one column, right inputs, useful errors
Most form problems are solved by four habits: a visible label above every field, a single column, the input type that matches the data, and error messages that say exactly how to fix the problem. Get those right and a form feels short even when it isn't.
Labels: visible, above, and never only a placeholder
The first of the web form design best practices is the simplest: every field needs a label that stays on screen while someone types. Placeholder text inside the field disappears on the first keystroke, is usually too faint to pass contrast, and leaves people who return to a half-finished form guessing what each box was for. Put the label above the field, where it's read just before the input and doesn't fight for horizontal space on phones. Associate it in the markup (label for matching the input's id, or the input inside the label) so screen readers announce it and clicking the label focuses the field.
Placeholders can still help with format examples, such as “e.g. 07700 900123”, but a hint below the label is more reliable, because it doesn't vanish.
Layout: one column, grouped, in a sensible order
- One column. The eye moves straight down; nobody misses a field on the right. The common exception is genuinely paired short fields, like a date and a time, side by side on wide screens.
- Group related fields with
fieldsetandlegend: “Your details”, “The job”, “When”. Radio buttons and checkbox sets always belong in a fieldset, so the question is read with each option. - Order fields as people think. Name before email, the problem before the date, the address in the order the country writes it.
- Size inputs to their content. A postcode field doesn't need to be as wide as a message box; widths hint at what's expected.
- One primary button at the end, aligned with the fields, with a label that says what happens.
The right input for each kind of data
| Data | Markup | Why |
|---|---|---|
type="email" autocomplete="email" | Email keyboard on phones, browser autofill | |
| Phone | type="tel" autocomplete="tel" | Number pad; doesn't force a format |
| Whole numbers | inputmode="numeric" | Number pad without the quirks of type=number |
| Date | type="date" or three fields for birth dates | Native picker for near dates; typing is faster for distant ones |
| A choice of 2 to 5 | Radio buttons | All options visible at once |
| A choice of many | A select, or a searchable list | Saves space; harder to scan |
| Long text | textarea with a character limit | Room to write, and a clear ceiling |
Set text inputs to at least 16px to stop iOS Safari zooming in on focus, and make fields at least 44px tall. Use autocomplete values wherever they apply; WCAG asks for them on fields that collect information about the user.
Validation: when it runs
Validating as someone types tells them they're wrong before they've finished. Validating only on submit makes them hunt. The middle path works best: check a field when the person leaves it, and recheck as they correct it. CSS can help: the :user-invalid pseudo-class applies only after the user has interacted with a field, unlike :invalid, which can paint an empty form red on load. On submit, if there are errors, move focus to a summary at the top or to the first invalid field.
Error messages that fix the problem
| Unhelpful | Helpful |
|---|---|
| Invalid input | Enter an email address with an @, like name@domain.co.uk |
| Field required | Enter your phone number so we can confirm the booking |
| Error | Choose a date from tomorrow onwards |
| Password does not meet requirements | Use at least 12 characters |
Put the message next to the field, in text, connected with aria-describedby so it's read with the field. Don't rely on a red border alone: some people can't see the colour change, and it says nothing about what's wrong. Never clear what someone typed because one field failed. There's more on wording in form error messages.
Forms in Anticode
Anticode's forms follow most of these rules by default: labels above fields, one column on phones, fields typed for their data, text at 16px, and invalid fields marked only after interaction. Before publishing, Sentinel fails the page if any field has no label, and also checks that text fields have a type and a length limit and that every form posts to the site's own address. Contact, booking and newsletter forms send to Anticode's form pipeline, where submissions are saved and sealed at rest.
Booking forms group time slots as radio buttons in a fieldset with a legend. For the contact form specifically, which fields to ask for and what to say next to it, see contact form design.
Questions people ask
Can placeholder text replace labels?
No. Placeholders disappear when typing starts and are often too faint to read. Use a visible label and, if needed, a hint below it.
Should labels go above or beside fields?
Above, for most web forms. It's faster to scan, works at every screen width and keeps the label close to the field on phones.
When should form validation run?
When the person leaves a field, and again as they fix it. Avoid flagging errors while they're still typing or before they've touched the form.