Chapter 42 — Forms, Validation and UX Writing
Section 1 — What a form is really for
A form is not a collection of boxes on a page. It is a conversation with a job to do. The person using it wants something: to sign up, to buy, to apply, to send a message, to change a setting. The form is the route to that outcome, and every field should earn its place by helping the person reach it. When you start designing a form, start with the outcome, not with the fields. Ask what the smallest set of information is that lets the next step happen. A newsletter signup may need only an email address. A job application needs more, but it still does not need everything on the first screen. Extra fields are not harmless decoration. Each one adds reading, thinking, typing, and a chance to make a mistake or give up, so removing a field is often the most useful improvement you can make.
Think about the person filling the form, not the database behind it. Databases like neat columns, but people arrive distracted, on phones, in noisy places, and sometimes in a hurry. They may not know an answer in the exact format you expect, or they may have the information in a different form from the one you ask for. A good form accepts human variation where it can. It lets someone type a phone number with spaces or dashes, it explains why a piece of information is needed when the reason is not obvious, and it does not punish a small difference in format. The form's job is to collect what is needed with the least friction and the least doubt, and then to confirm clearly that the job is done.
A form also has a back end, even if this chapter focuses on the front end. When the person presses submit, the browser gathers the named fields and sends them to a server, which checks them again, stores them, or acts on them. Front-end validation can catch obvious mistakes early, but it can never be the only check, because anyone can bypass code that runs in the browser. Treat front-end work as help for the honest user: fast feedback, clear guidance, and a smooth path. Treat server checks as the real gate. Designing with both in mind keeps you from making promises the front end cannot keep, such as claiming a username is available before the server has confirmed it.
Finally, judge a form by what happens after it, not by how it looks in a design file. Can a person complete it with a keyboard alone? Can a screen reader user understand every field and every error? Does it work when a connection is slow, when an answer is pasted rather than typed, or when the person goes back to fix one field without losing the rest? Those are the tests that matter. A beautiful form that loses data, hides its errors, or blocks people who use assistive technology has failed, however polished it appears. Build the form around the task, keep it as short as honesty allows, and make every step explain itself.
Check: What is the first question to ask before adding a field to a form?
Section 2 — Labels are the field's name
Every form control needs a visible label, and that label must be properly connected to the control. A label is not decoration above a box. It is the field's name, the words a person reads to know what to type, and the words a screen reader announces when the field receives focus. When a label is connected with the for attribute matching the control's id, clicking the label also moves focus to the control, which makes checkboxes and radio buttons much easier to tap. That connection is cheap to add and expensive to lose, because without it, assistive technology may announce only a bare input with no meaning, and the person has to guess from surrounding text what is wanted.
Write labels as clear questions or short noun phrases, not as clever hints. "Email address" is better than "Your best email here!" because it says exactly what belongs in the box. "Full name" is usually better than "Name", because it tells the person whether to include a family name, though later sections explain why even "full name" is not always the right choice. Keep labels short, but not at the cost of clarity. If a field needs a format, such as a date, put the format in help text near the field rather than cramming it into the label, and keep the label itself as the plain name of the thing being asked for. Consistency helps too: if one field says "Email address", another should not say "E-mail" or "Contact email" for the same idea.
Position matters as well. Labels above fields are the safest default. They stay visible while the person types, they work well on narrow screens, and they leave room for help text and error messages below. Labels to the left of fields can work on wide desktop layouts, but they break on phones, where the label and the field compete for a narrow width. Labels inside fields, as placeholders, are not labels at all, and the next section explains why that shortcut fails. If a design places labels in an unusual position, test it with real content: long labels, large text sizes, translated text, and error messages added below. A layout that only works with short English labels at one size is not finished.
A common mistake is to rely on colour, an asterisk alone, or an icon to carry meaning that the label should carry. A red asterisk may signal "required" to a sighted user who knows the convention, but it says nothing on its own to a screen reader unless the text also says "required", and it is invisible to someone who cannot distinguish the colour. Similarly, an icon of an envelope next to an email field is a helpful visual cue, but it is not a substitute for the words "Email address". Check your own work by turning off styles, zooming the page, and tabbing through the form with a keyboard. If every field still announces its name, its purpose, and whether it is required, the labels are doing their job.
Check: Why must a label be connected to its control, not just placed near it?
Section 3 — Input types tell the browser what you expect
HTML provides many input types, and choosing the right one is one of the simplest ways to make a form easier. An email field should use type="email", a telephone field type="tel", a web address type="url", a number type="number" only where a true number is meant, and a date type="date" where a calendar date is meant. Each type gives the browser a hint about what to check, what keyboard to show on a phone, and how to help the user. An email type on a phone typically brings up a keyboard with an at sign and a dot within reach. A telephone type brings up a numeric keypad. Those small helps add up, especially for people typing on small screens, and they cost you nothing more than choosing the correct type in the first place.
The type also affects built-in validation. A browser will refuse to submit an email field that contains no at sign, and it will treat a URL field similarly. That is useful, but it is not a complete check. Built-in email validation is deliberately loose: it checks the shape of the address, not whether the mailbox exists or belongs to the person typing. You should not claim an address is valid just because the browser accepted it, and you should not reject addresses that look unusual but are technically correct. Use the type as a first filter and a keyboard hint, then let the server do the serious checking, and use a confirmation step, such as a verification link, where an address truly matters.
Choosing the wrong type creates real problems. Using type="number" for a phone number, a postcode, or a card number is a classic error. Numbers in those fields are identifiers, not quantities: nobody adds two phone numbers together, and leading zeroes matter. A number input may strip leading zeroes, show spinner buttons that nobody asked for, and refuse characters such as plus signs and spaces that people naturally include in phone numbers. For identifiers that look numeric, use type="text" with an appropriate input mode, which a later section covers, or type="tel" for phone numbers. The same care applies to dates: a date input gives a browser calendar picker, which helps many users, but its appearance varies between browsers, and some users prefer to type, so test both paths rather than assuming the picker solves everything.
When you are unsure which type fits, ask two questions: what kind of value is this, and what would help the person enter it? If the answer is a quantity you might calculate with, a number type may fit. If it is an identifier, a code, or a telephone number, text or tel is safer. If it is a secret, password is the right type, with the show-and-hide behaviour covered later. Always test on a real phone, because desktop browsers hide the keyboard difference that makes the type choice matter most. A form that feels fine with a full keyboard can feel clumsy on a phone if every field brings up the wrong keyboard, and that friction is entirely avoidable.
Check: Why is type="number" wrong for a phone number?
Section 4 — Placeholders are not labels
A placeholder is the faint text inside an empty field, shown as an example or a hint. It looks like a tidy solution: the field explains itself without taking up space for a label. In practice, it fails as a label for several reasons, and those reasons matter enough that you should treat "placeholder as label" as a mistake to avoid, not a style to copy. The first problem is disappearance. The moment a person starts typing, the placeholder vanishes, so anyone who forgets what the field asked for must delete their answer to see the hint again. That is a small annoyance for a short field and a real obstacle for a long one, or for someone who is interrupted mid-form and returns to a half-filled field with no visible names.
The second problem is contrast and readability. Placeholder text is usually shown in a lighter colour than normal text, which can be hard to read for people with low vision or on screens in bright light. Browsers style it faintly on purpose, to distinguish it from a real answer, but that distinction works against anyone who struggles to read faint text. The third problem is confusion with a filled value. Some users, especially those less familiar with forms, mistake placeholder text for an answer already present, and either leave the field thinking it is done or worry that they must delete text that is not really there. Screen readers also handle placeholders inconsistently: some announce them, some do not, and none treats a placeholder as a reliable replacement for a label.
None of this means placeholders are useless. Used well, a placeholder shows a brief example of the expected format, such as example: jane@example.com in an email field that already has a visible label "Email address". The example helps the person see the shape of a good answer without pretending to be the field's name. Keep placeholders short, never put essential instructions only in a placeholder, and never put a password hint or a critical warning there, because it will vanish exactly when the person needs it. If the information matters, put it in persistent help text below the label or beside the field, where it stays visible while typing.
Check your own forms by filling them slowly and then pausing. Can you still tell, at a glance, what every filled field is for, without deleting anything? If the answer depends on remembering placeholder text that is now gone, add visible labels. Also check with the browser's autofill: when the browser fills a field, the placeholder disappears and the label remains, which is exactly the behaviour you want. A form that only makes sense when every field is empty has been designed for a screenshot, not for a person actually using it.
Check: Name two reasons a placeholder cannot replace a label.
Section 5 — Marking required and optional fields clearly
Every field should make it obvious whether it is required or optional, and the method should work for everyone, not just for sighted users who know a particular symbol. The most reliable approach is to write the word itself. Put "(required)" or "(optional)" in or near the label, or state at the top of the form which convention you use and then apply it without exception. For example, if you mark optional fields, say "All fields are required unless marked optional" at the top, and then mark every optional field. If you mark required fields, say so at the top and mark every required field. The key is consistency: a convention that is applied to most fields but forgotten on one is worse than no convention, because it teaches the user to trust a signal that then misleads them.
Symbols alone are not enough. An asterisk is the traditional mark for a required field, and many users recognise it, but it carries no meaning on its own for a screen reader unless it is explained in text, and it is meaningless to someone who has never learned the convention. If you use an asterisk, pair it with text: either write "(required)" as well, or explain at the top, "Fields marked with * are required", and make sure the required state is also present in the field's accessible name or description, not only as a visual star. Colour alone is even weaker. A red label or a red asterisk says nothing to a person who cannot see the colour, and it may be missed by anyone scanning quickly. Words are the accessible signal; symbols and colour can reinforce them, but never replace them.
Think carefully about whether a field truly needs to be required. Each required field is a barrier, and a form that demands a phone number for a newsletter, or a company name from a private individual, will lose people or collect invented answers. Ask whether the task can proceed without the information, whether it can be collected later when the relationship is established, or whether a sensible default exists. When a field is optional, saying so explicitly is a kindness: it tells the person they can skip it without penalty, and it removes the guilt and guessing that an unmarked field creates. People who want to provide extra detail still can, and people who do not are not blocked.
Finally, required marking on the front end must match the server. If the front end calls a field optional but the server rejects a submission without it, the person receives a confusing error for a field they were told they could skip. If the front end calls a field required but the server does not need it, you are blocking people for no reason. Keep a single list of required fields for each form, shared between front-end and back-end checks, and review it whenever the form changes. Test the edge cases: submit with only the required fields filled, submit with an optional field left blank, and submit with an optional field filled badly. All three should behave sensibly, with clear messages when something is genuinely missing.
Check: Why is an asterisk on its own not a sufficient required marker?
Section 6 — Grouping fields so the form reads like a story
A long form feels shorter when it is grouped into sections that follow the order a person thinks in. Grouping is done with the fieldset element and its legend, which names the group. A checkout form might group "Delivery address", then "Payment", then "Review". A profile form might group "About you", then "Contact details", then "Preferences". The legend is announced by screen readers as the group name, so a person moving through the fields hears the context for each one, not just a list of unrelated boxes. Visually, a group can be separated by spacing and a heading, but the fieldset gives that grouping real structure, not just a visual gap.
Order the groups and the fields inside them the way a person would naturally answer. Put name before email if that is the order in which someone introduces themselves, and put a delivery address before payment details if the delivery choice affects the cost. Avoid asking for information in the order that suits your database tables. Database order is an implementation detail; human order is the interface. Within a group, keep the most common path first. If most users choose the same delivery option or the same account type, that option should be easy to reach, not buried at the bottom after rare alternatives. When a choice changes what follows, such as a country choice changing the address fields, make that relationship visible rather than surprising the user with a sudden rearrangement.
Grouping also helps with errors and progress. In a multi-step form, each step is a group with a clear name, and the person can see how many steps remain. In a single long form, group headings act as landmarks: a person who returns after an interruption can find "Payment" quickly instead of scanning every field. When an error occurs, the group name helps locate it: "In Delivery address, the postcode is missing" is far more useful than a bare "Postcode is missing" on a form that has two postcodes. Keep group names short and plain, and do not nest groups so deeply that the structure itself becomes a puzzle. Two or three levels at most, and usually one, is enough.
A common mistake is to group by visual convenience rather than meaning, for example putting two unrelated short fields side by side just because they fit. Side-by-side fields are covered later, but the principle here is the same: layout should follow meaning. If two fields belong to different ideas, keep them in different groups even if the page would look tidier with them together. Test grouping by reading only the group names and field labels aloud, in order. If that reading sounds like a sensible conversation — who you are, where to send it, how to pay — the grouping works. If it jumps between topics without reason, reorder it before you worry about styling.
Check: What does a legend give a group of fields that spacing alone does not?
Section 7 — One column, one idea at a time
For most forms, a single column is the safest layout. One field follows another down the page, each with its label above it, its help text nearby, and its error message below it when needed. This layout works on phones without adjustment, it works with large text sizes, and it works with screen readers, because the reading order matches the visual order. It also matches how people actually complete forms: they answer one question, move to the next, and rarely need to compare two fields side by side. When a layout is simple, the person's attention stays on the questions, not on figuring out where to look next.
Multi-column layouts tempt designers because they make a long form look shorter. Two columns halve the vertical length on a desktop screen, but they create a new problem: the eye must decide whether to read across the row or down the column, and different people choose differently. A person who reads down the left column and then down the right column may answer fields in a different order from the one the form expects, and a screen reader will follow the document order, which may not match either visual path. The result is skipped fields, answers in the wrong boxes, and errors that feel unfair because the person followed a layout that the form itself suggested. Short related pairs, such as a first name and a family name, or a month and a year, are the exception, and even those should stack on narrow screens.
If you do place two fields side by side, keep the pairing meaningful and the order obvious. Related fields that form one idea, like a city and a postcode, can sit together, but unrelated fields should not share a row merely to save space. Make sure the tab order follows the visual order, left to right and then down, and test it with a keyboard, because a tab order that jumps across columns will confuse keyboard users even when the visual layout looks neat. On a phone, always stack: there is no width to spare, and a half-width field on a phone is a small tap target and a cramped typing area. A responsive rule that stacks fields below a comfortable width is not a compromise; it is the layout working as intended.
Judge a layout by watching someone use it, or by using it yourself under awkward conditions. Fill it on a phone with one hand, fill it with text zoomed to twice its size, fill it using only the keyboard. If any of those experiences forces you to hunt for the next field, the layout is costing more than the space it saves. Single-column forms may look plain in a design file, but plain is not a flaw when the job is to collect answers accurately. Save visual excitement for the surrounding page; let the form itself be calm, predictable, and easy to move through.
Check: Why does a two-column form often cause answers in the wrong boxes?
Section 8 — Names, values and what submit actually sends
When a form is submitted, the browser does not send the labels, the help text, or the layout. It sends pairs of names and values: each control's name attribute and the value the person entered or chose. If a control has no name, its value is not sent at all, which is a quiet and common bug. A beautifully built field that lacks a name will look finished in the browser and arrive empty at the server. Always give every control that should be submitted a clear, consistent name, and check the submitted data, not just the visible form, when testing. The name is the contract between the front end and the server, and both sides must agree on it.
Values come in different shapes depending on the control. A text field sends the text typed. A checkbox sends its value only when it is checked; when it is unchecked, it sends nothing, which means the server must treat "absent" as "not checked" rather than expecting an explicit "no". A group of radio buttons with the same name sends the value of the selected button, and only one can be selected. A select list sends the value of the chosen option, which may differ from the visible text: the option text might say "United Kingdom" while its value is a short code. Keeping the visible text human-readable and the value machine-friendly is good practice, but the two must stay in sync, or the server will record something the person never saw.
The value attribute also sets a starting point. For a text field, it pre-fills the field. For a checkbox or radio button, it defines what is sent when that option is chosen. For a submit button, it sets the button's label. Prefilling can help when you already know an answer, such as an email address from a previous step, but prefill with care: a wrong prefilled value that the person overlooks is worse than a blank field, because it looks intentional. Never prefill a password, a payment detail, or any sensitive value, and never use a value as a substitute for a label or help text, since it disappears when the person types over it or may be submitted unchanged by mistake.
Finally, understand that the submitted data is only as trustworthy as the checks behind it. A person can edit values in developer tools before submitting, so the server must validate every name and value it receives, reject unexpected values, and never assume that a value came from your form's options. On the front end, your job is to make the honest path easy: clear names, sensible values, no missing names, and a submit button that does what it says. Test submission by inspecting what is actually sent, using the browser's network tools, rather than assuming the visible form and the sent data match. When they do match, the form is ready to be trusted.
Check: What happens to a field that has no name attribute when the form is submitted?
Section 9 — GET and POST, and which one a form should use
A form's method attribute chooses how its data travels to the server. The two common choices are GET and POST, and they are not interchangeable. With GET, the form's values are added to the URL as a query string, visible in the address bar, saved in browser history, and possibly stored in server logs. With POST, the values travel in the body of the request, not in the URL, so they do not appear in the address bar and are not bookmarked as part of the URL. That single difference drives most of the decision about which method to use.
GET is right for requests that only retrieve something and change nothing. A search form is the classic example: the query in the URL means the results page can be bookmarked, shared, and revisited, and pressing the back button behaves sensibly. A filter form on a product list is similar: the chosen filters belong in the URL so that a link to that filtered view works for someone else. Because GET requests are meant to be safe to repeat, a browser may resend one without warning, and a search engine may follow one. Never use GET for an action that changes something, such as placing an order, changing a password, or deleting an account, because the URL could then be revisited, shared, or indexed, and the action could be repeated unintentionally.
POST is right for actions that change state or carry sensitive or large data. Creating an account, submitting an application, sending a message, uploading a file, or completing a purchase should all use POST. The data is not in the URL, so it is not left in history or shared by copying a link, though POST alone does not encrypt anything: encryption comes from HTTPS, which you should use for every form that carries personal data. POST also signals to the browser that resubmitting may repeat an action, which is why browsers warn before resending a POST request when the back button is used. That warning is a useful guard against duplicate orders and duplicate messages.
A common mistake is to leave the method unset. Without a method, a form defaults to GET, which means a contact form or a signup form may silently put personal data into the URL. Always set the method deliberately, and set the action attribute to the address that should receive the data, even if you plan to handle submission with JavaScript. JavaScript can intercept the submit event and send the data another way, but the form should still have a sensible method and action as a fallback, so that it works when JavaScript fails or is unavailable. Check your choice by asking one question: if someone shared this URL, or refreshed this page, would anything happen twice or leak? If the answer is yes, the method is wrong.
Check: Why should a search form use GET but an order form use POST?
Section 10 — Autocomplete helps people finish faster
Autocomplete is a browser feature that fills fields with information the person has already given to the browser, such as their name, address, or payment details, when the field's autocomplete attribute names the right kind of data. Setting autocomplete="email" on an email field, autocomplete="given-name" on a first-name field, and autocomplete="postal-code" on a postcode field tells the browser what each field is for, so it can offer the correct saved value instead of guessing from the label. When it works, the person taps once instead of typing a whole address, which is faster, more accurate, and much kinder on a phone. When it is missing or wrong, the browser may offer the wrong value, or offer nothing, and the person must type everything by hand.
Getting autocomplete right requires using the standard token names, not inventing your own. The standard list covers names, addresses broken into parts, telephone numbers, email addresses, and payment details, among others. Use the most specific token that fits: a field for a full street address is not the same as a field for a house number, and a field for a new password is not the same as a field for a current password. Payment and password fields deserve special care, covered in later sections, because the browser treats them with extra caution. If your form uses unusual labels or splits an address in an unusual way, check the standard tokens first and reshape the fields to match them, rather than expecting the browser to understand a custom scheme.
Autocomplete also has limits you should respect. It only helps if the person has saved the information and has allowed the browser to use it. Some people clear saved data, use a shared device, or prefer to type, so autocomplete must never be required for a form to work. Do not disable it casually: setting autocomplete="off" on a whole form, or on fields where it would help, removes a genuine accessibility and convenience aid, and browsers may ignore the instruction on login and payment fields anyway. If there is a genuine reason to disable it for one field, such as a one-time code, disable it for that field only, and explain the reason in your notes, not in the user interface.
Test autocomplete with a real browser profile that has saved data, and test it after a failed submission too: the browser should still offer values, and your form should not wipe them when it re-displays with errors. Also test on a phone, where the difference between a helpful suggestion and a blank field is largest. A form that respects autocomplete feels like it is on the person's side, because it reuses work they have already done instead of demanding it again. That feeling is worth the small effort of adding the correct attributes to every field where a standard token exists.
Check: What does the autocomplete attribute tell the browser?
Section 11 — Keyboards, input modes and mobile typing
On a phone, the keyboard is part of the form. The inputmode attribute tells the browser which keyboard layout to show for a text field, without changing the kind of value the field accepts. A postcode field might use inputmode="text" with a suitable pattern, an amount field inputmode="decimal", and a one-time code field inputmode="numeric". The difference from type="number" is important: inputmode changes only the keyboard, while the value stays text, so leading zeroes, plus signs, and spaces are preserved. For fields that accept digits as identifiers, such as codes and phone numbers, that preservation matters, and inputmode gives you the convenient keypad without the data damage that a number input can cause.
Choosing a keyboard is a small act of respect for the person's time. A numeric keypad for a code means fewer taps and fewer mistakes than a full letter keyboard where the digits are on a second screen. A decimal keyboard for a price means the decimal point is within reach. An email keyboard puts the at sign and dot where they are easy to find. None of these choices changes the validation rules, and none replaces them: a numeric keyboard does not guarantee a numeric value, because a person can paste text or switch keyboards, so the server and the front-end checks must still validate the value itself. Think of inputmode as a hint to the device, not a rule enforced by it.
Also consider the size of the tap and typing area. On a phone, a field that is only one line high and narrow is hard to tap accurately, especially for someone with limited dexterity or a cracked screen protector. Give fields a comfortable height, generous spacing, and a tap target that does not require precision. Avoid placing a small button or a tiny link immediately beside a field where a mistap could clear or submit the form. Test with your thumb, not just a mouse: if you must aim carefully, the target is too small. The same applies to dropdowns and date pickers, which are covered later; on a phone, the browser's native picker is often easier than a custom one that was designed with a mouse in mind.
Finally, do not assume a phone is the only small-screen case. Tablets in split-screen mode, laptops with touchscreens, and desktop browsers zoomed to large text all benefit from the same care. A field that works when typed with a full keyboard and clicked with a mouse should also work when typed with a thumb and tapped with a finger. Check the whole form on a real phone, in portrait orientation, with the keyboard open, because the keyboard covers half the screen and can hide the submit button, the error message, or the next field. If the person cannot see what went wrong while the keyboard is open, the form has a mobile problem that no desktop test will reveal.
Check: What is the difference between inputmode and type="number"?
Section 12 — Dates, times and numbers without traps
Dates, times, and numbers look simple, but they hide traps that catch forms again and again. A date input gives a calendar picker in many browsers, which avoids the ambiguity of typed formats, but its display depends on the browser and the person's locale, and its value is always sent in a standard year-month-day format behind the scenes. That separation is useful: the person sees a familiar local format, and the server receives a consistent one. The trap is assuming every browser shows the same picker, or that every user likes picking from a calendar. Some people, especially those entering many dates, prefer to type, and a date input that forces a picker can slow them down. Test both typing and picking, and consider whether a set of clearly labelled fields or a text field with a clear format hint suits your audience better.
Typed dates bring their own ambiguity. The string 03/04/2026 means 3 April in most of the world and March 4 in the United States. A form that accepts a typed date without stating the expected order will collect wrong dates from careful people who followed a different convention. If you accept typed dates, state the order explicitly, for example "Day, month, year", and validate it strictly on the server, rejecting impossible dates such as 31 February rather than silently converting them. The same applies to times: state whether a time is in a twelve-hour or twenty-four-hour format, and whether a timezone matters. A meeting time without a timezone is not a complete time, and a form that collects one without saying so will cause missed meetings.
Numbers have traps of a different kind. A quantity field should accept the values people actually use, including decimals where they make sense, and should reject nonsense without a confusing message. A price field that rejects a decimal point, or a quantity field that accepts a negative number for an order, is badly specified. Set minimum and maximum values where they are genuinely meaningful, and use step values carefully: a step of one makes sense for a count of items, but not for a weight that may be fractional. Show the unit beside the field, such as kilograms or litres, rather than leaving the person to guess whether to type grams or kilograms. Units that are left implicit are a reliable source of errors.
The general rule for all three kinds of field is to be explicit about format, unit, and range before the person types, and to be forgiving about harmless variation after they type, such as spaces around a number. Strip harmless whitespace, accept a decimal point in the expected place, and only complain when the value is genuinely unusable, with a message that says what is acceptable. A form that rejects a correct answer because it was typed in a slightly different but understandable way has mistaken strictness for correctness, and it will frustrate exactly the careful users it should be helping.
Check: Why is a typed date like 03/04/2026 risky without a stated order?
Section 13 — Choosing between select, radio and checkbox
When a person must choose from a list, the control you pick changes how easy the choice is. Radio buttons suit a short list where the person should see all options at once and pick exactly one. Checkboxes suit a list where more than one option may be chosen. A select dropdown suits a long list, such as a country list, where showing every option would overwhelm the page. The rule of thumb is simple: if the list is short, show it; if it is long, hide it behind a dropdown; if more than one answer is allowed, use checkboxes. Following that rule prevents the two common mistakes: a dropdown with only two options, which hides a trivial choice behind an extra click, and a radio list with fifty options, which turns a simple choice into a long scroll.
Radio buttons and checkboxes have a usability advantage that dropdowns lack: the options are visible without interaction, so the person can compare them, and the selection is visible without opening anything. That matters when the choice is important or unfamiliar, such as choosing a delivery method with different prices and speeds. Show the price and the consequence beside each radio option, not hidden in a dropdown where the person must open it to compare. For checkboxes, make each option's label clear and its tap target generous, since clicking a small box precisely is harder than clicking its label, which should also select it when properly connected.
Dropdowns, by contrast, are best when the person already knows their answer and just needs to find it, as with a country or a language. Even then, a very long dropdown is hard to use on a phone, where the native picker takes over the screen, and hard to search on a desktop unless the browser allows typing to jump to an entry. Consider whether a text field with suggestions, or a grouped list, would serve better than a raw list of hundreds of items. If you must use a long dropdown, put the most likely options first where that is honest, keep the list in a sensible order, such as alphabetical, and never use a dropdown for a value the person could type more easily, such as a year of birth spread over a century.
There is also an honesty question in defaults. A preselected radio button or dropdown option looks helpful, but it can also record an answer the person never chose, especially if they skim past the field. For choices that matter, such as consent, payment method, or a subscription, start with no option selected and require a deliberate choice, even if that adds one click. For choices where a default is genuinely the common case and easily changed, a default is fine, but make it visible and easy to undo. Test the choice controls with a keyboard and a screen reader, and by answering quickly without reading carefully: the form should make an accidental wrong choice unlikely, and a deliberate choice easy.
Check: When is a dropdown a better choice than radio buttons?
Section 14 — Textareas, counts and long answers
A textarea is for answers longer than a single line: a message, a description, a comment, or a reason. Unlike a single-line text field, it can grow, wrap, and hold paragraphs, and it should be sized to suggest the length of answer expected. A textarea only one line high signals a short answer, while one five or six lines high invites a fuller one. That sizing is communication: people adjust their answers to the space offered, so a feedback box that looks tiny will receive brief feedback, and a box that looks generous will receive more detail. Choose the height deliberately, and consider letting the box grow as the person types, while keeping a sensible maximum so it does not swallow the page.
Character and word counts help when there is a genuine limit, but they must be handled with care. A limit exists to keep answers manageable for the people who read them, not to punish the writer. Show the count clearly, update it as the person types, and announce changes accessibly rather than updating a number silently that a screen reader never hears. The most helpful pattern is to show how many characters remain, or how many words have been used, in plain words near the field, and to warn before the limit is reached rather than only after it is exceeded. A count that only appears as an error after submission is too late to help.
Do not enforce a limit by silently cutting off typing. When a person types past a limit and their words vanish without explanation, they may not notice, and the submitted answer may end mid-sentence. A better approach is to allow typing, show that the limit is exceeded, and explain how much to remove, or to prevent submission with a clear message. For word limits, be explicit about what counts as a word, since hyphenated words and numbers can be counted differently, and do not let a counting quirk reject a good answer. If a limit is not truly needed, remove it: many forms impose a character limit out of habit, not because anyone will act on the difference between two hundred and three hundred characters.
Finally, preserve long answers. Nothing is more infuriating than writing a careful message, encountering an error elsewhere in the form, and returning to find the message gone. When a form is re-displayed after an error, every field, especially textareas, must retain what was typed. The same applies when the person navigates away and back, where a draft-saving approach, covered later, can help. Test this by writing a long answer, triggering an error in another field, and checking that the long answer survives. If it does not, the form is punishing effort, and people will learn not to give it.
Check: Why should a character limit not silently cut off typing?
Section 15 — Password fields and show-hide controls
A password field hides what is typed, replacing characters with dots or asterisks, so that someone looking over the person's shoulder cannot read it. That protection is real, but it creates a usability problem: the person cannot see their own typing, so a single mistyped character makes the whole password fail, and they cannot tell which character was wrong. The standard solution is a show-hide control, a button beside the field that toggles the password between hidden and visible. The button must be a real button, with a clear label such as "Show password" that changes to "Hide password" when active, not an icon alone that leaves the person guessing what it does.
Password rules should be shown before the person types, not revealed only as errors after submission. If a password must be at least a certain length, or must include certain kinds of characters, say so plainly beside the field. Do not impose arbitrary rules that do not improve security, such as forcing a symbol from a small set, banning spaces, or limiting the maximum length to a short number, because those rules frustrate people and push them toward weaker, predictable passwords. A long passphrase made of ordinary words is often stronger and easier to remember than a short string of mixed symbols, so allow long passwords and spaces, and judge strength honestly rather than with a coloured bar that rewards any mixture of characters regardless of length.
Confirmation fields, where the person types the password twice, are a legacy solution to the visibility problem, and they are usually worse than a show-hide control. Typing the same secret twice doubles the work and doubles the chance of a matching pair of mistakes, and it does not help the person who mistypes the same way twice. A single password field with a show-hide button, plus a clear path to reset a forgotten password, serves most cases better. If you must keep a confirmation field, for example because a system requires it, make the mismatch error precise and preserve both fields' contents so the person can fix one without retyping both.
Accessibility matters here too. The show-hide button must be reachable by keyboard, its state must be announced to screen readers, and toggling it must not move focus away from the password field or clear the password. Autocomplete attributes also matter: use the token for a current password on a login field and for a new password on a signup or change field, so password managers can offer and save correctly. Test the whole flow: create a password, show it to check it, hide it again, submit, and sign in again using the saved password. If any step fights the password manager or hides an error, the login experience will feel broken even when the account system works.
Check: Why is a show-hide button usually better than typing a password twice?
Section 16 — Email addresses and how to check them honestly
An email field looks simple, but checking it honestly requires restraint. The browser's built-in email check only verifies shape: it looks for an at sign and a plausible structure. That is a useful first filter, because it catches a missing at sign or a completely empty field, but it cannot tell whether the address exists, whether it belongs to the person typing, or whether it was mistyped in a way that still looks valid. An address such as a common name at a mistyped domain will pass every shape check and still never reach its owner. Do not tell a user their email is valid on the basis of shape alone, and do not reject addresses that are unusual but technically correct, such as those with a plus sign used for filtering.
The most common email mistake is a typo in the domain, and the most helpful front-end response is a gentle suggestion, not a block. If a person types a well-known domain with a small error, a suggestion such as "Did you mean example.com?" can save a lost account, but it must be offered as a question, not imposed as a correction, because the person's real domain might genuinely be the one they typed. Never auto-correct an email address silently: silently changing what a person typed replaces their answer with your guess, and if your guess is wrong, the account or message goes to a stranger. Offer, let the person accept or dismiss, and preserve their original typing if they dismiss the suggestion.
Confirmation email fields, where the person types the address twice, suffer from the same weakness as password confirmation: a person can mistype the same way twice, and the extra field adds work without guaranteeing accuracy. A better approach for cases where the address truly matters is a verification step: send a message to the address and ask the person to confirm it, and explain that step before they submit, so they expect the message and check the right inbox. For less critical cases, a single well-labelled email field with a clear suggestion mechanism is enough, and the confirmation field can be dropped.
Finally, remember that email addresses are personal data. Do not display a full address back in a public place, do not use it for purposes the person did not agree to, and do not require an email address when another contact method would do. When a form does require one, explain why, in plain words, near the field. "We need an email address to send your receipt" is honest and specific, while "Enter your email" alone leaves the person guessing whether they will receive marketing. That explanation builds trust, and it also reduces fake addresses, because people who understand the reason are more willing to give a real one.
Check: Why should a form never silently auto-correct an email address?
Section 17 — Built-in validation with required and friends
HTML gives you built-in validation that works without any JavaScript: required for fields that must be filled, type for shape, min and max for numbers and dates, minlength and maxlength for text length, and pattern for a regular expression the value must match. When a form with these attributes is submitted, the browser checks the fields, stops submission if something fails, and shows a message near the offending field, focusing it so the person can fix it. That behaviour is free, accessible in most browsers, and consistent enough to be a genuine starting point. Use it for every rule that HTML can express, before writing any custom code.
Built-in validation has limits you should know. The browser's messages are written in the browser's language and style, which you can only partly control, and they vary between browsers. A message that reads clearly in one browser may read tersely in another. The messages also appear only at submission time, which means a person can fill a long form, press submit, and only then learn about a problem in the first field. For short forms, that is acceptable. For long forms, earlier feedback, covered in a later section, is kinder. Built-in validation also cannot express rules that depend on two fields together, such as "end date must be after start date", or rules that need server data, such as "this username is taken". Those need custom code, and sometimes server checks.
A practical approach is to layer validation. Start with HTML attributes for the simple, universal rules: required fields, email shape, number ranges, and text lengths that are genuinely meaningful. Add custom JavaScript only where HTML cannot express the rule, or where the built-in message would confuse your users. When you add custom code, keep the HTML attributes as well where they apply, so the form still has a baseline when JavaScript fails. Do not remove required just because you have custom code, and do not rely on JavaScript to enforce a rule that HTML already enforces, unless you have a clear reason, such as needing a message in the user's language.
Test built-in validation in more than one browser, with a keyboard, and with a screen reader. Check that the error message is announced, that focus moves to the problem field, and that fixing the field and resubmitting clears the error. Check also that a field marked required is genuinely required by the server, and that a field with a pattern has help text explaining the pattern, because a person cannot guess a regular expression from an error message that says only "Please match the requested format". Built-in validation is a foundation, not a finished product, but a form that uses it well is already far ahead of one that validates nothing until the server replies.
Check: What does the browser do when a required field is empty at submit time?
Section 18 — Patterns, ranges and lengths done carefully
The pattern attribute lets you require a value to match a regular expression, a compact description of a text shape. It is powerful, and it is easy to misuse. A pattern for a postcode, a code, or an identifier can catch obvious mistakes, but a pattern written too strictly will reject valid answers from people whose real data does not fit your assumption. Postcodes vary by country, names contain characters beyond plain letters, and codes gain new formats over time. Before writing a pattern, ask whether the format is truly fixed and universal for your users. If it is not, a looser check, or no pattern at all with a server check, is safer than a strict pattern that blocks real people.
When you do use a pattern, always explain it in plain words beside the field. A pattern is invisible to the person filling the form, so an error message that says "match the requested format" without saying what the format is leaves them guessing. Write help text such as "Enter the code as three letters followed by four digits, for example ABC1234", and make sure the example itself matches the pattern. Test the pattern with valid answers from the edges of your audience: the longest and shortest valid values, values with spaces, hyphens, and accented characters, and values that a previous version of the pattern might have rejected. If a valid answer fails, the pattern is wrong, not the user.
Ranges and lengths need the same care. A min and max on a number field should reflect a real rule, such as "quantity must be between one and ten", not a guess about what people might order. A maxlength on a text field should reflect a real storage or display limit, and if the limit is reached, the person should be warned before submission, not discover it only when their text is cut off. A minlength should not force a person to pad a short but genuine answer to reach an arbitrary length. For every constraint, be able to answer the question "what breaks if this value is outside the range?" If nothing breaks, the constraint is decoration, and decoration that blocks submissions is a bug.
Finally, remember that patterns, ranges, and lengths are front-end conveniences, not security. A person can bypass them in developer tools, so the server must enforce the same rules. Keep the front-end and server rules in sync by deriving them from one shared description where possible, or at least by reviewing both whenever one changes. A mismatch in either direction is a defect: a front-end rule stricter than the server's blocks valid submissions, and a server rule stricter than the front end's produces a confusing error after the person believed the form was correct.
Check: Why must a pattern always be explained in plain help text?
Section 19 — Custom messages without confusing people
Sometimes the browser's built-in message is not clear enough, and you need a custom message. HTML and JavaScript provide a way to set one: a script can call setCustomValidity() on a field with a message, and the browser will show that message instead of its own when the field fails. Clearing it, by calling the same method with an empty string, restores normal behaviour. This tool is useful when a rule is specific to your form, such as "End date must be after start date", where the generic browser message would not explain the real problem. Used well, a custom message turns a cryptic failure into a fixable instruction.
Custom messages must be written as instructions, not accusations. "Enter a date after 12 May 2026" helps; "Invalid date" does not, because it does not say what is wrong or how to fix it. Write the message in the same plain language as the rest of the form, keep it short, and make it specific to the actual failure. If a field can fail in several ways, set a different message for each way, rather than one generic message for all of them. A person who left a field blank needs a different instruction from a person who entered a value in the wrong format, and a single message that covers both will confuse at least one of them.
Timing matters as much as wording. A custom message should be set when the value is known to be wrong, and cleared as soon as the person starts fixing it, so that a corrected field does not keep showing an old error. A common bug is to set a custom message on submit and never clear it, so that even after the person fixes the value, the form still refuses to submit, with no visible reason. Test this cycle explicitly: trigger the error, fix the value, and submit again without reloading. If the second submission still fails, the clearing logic is broken. Also test that a custom message does not appear before the person has had a chance to answer, which happens when validation runs too eagerly on page load.
Do not use custom messages to hide a design problem. If you find yourself writing a long custom message to explain a field, the field itself may need better labelling, help text, or a different control. A message is a repair, not a design. Keep messages short, keep them in the user's language where possible, and keep the built-in messages where they already work well. The goal is a form where most people never see an error message at all, and those who do see one that tells them, in plain words, exactly what to change and why.
Check: What must a script do after a person fixes a field with a custom message?
Section 20 — When to validate: blur, submit, or live
Validation timing decides whether feedback feels helpful or nagging. The three common moments are on submit, on blur (when a field loses focus), and live, as the person types. Each has a place, and using the wrong one at the wrong time is a common source of frustration. Submit-time validation is the baseline: it checks everything at once, when the person has declared they are done. It is honest, because it does not interrupt someone mid-thought, but it can feel late on a long form, where the first error may be far above the submit button. Blur validation checks a field when the person leaves it, which gives earlier feedback without interrupting typing, but it can still feel premature if the person tabbed through a field intending to return to it.
Live validation, checking on every keystroke, is the most intrusive and should be used sparingly. It can be helpful for a password strength hint or a character count, where the person benefits from seeing progress, but it is terrible for error messages. Telling a person their email is invalid after they have typed only the first letter is not feedback; it is noise, because no partial email is valid. Live error messages train people to ignore messages, since they have learned that messages appear even when they are doing nothing wrong. If you validate live, do it for positive or neutral information, such as a count, and reserve error messages for blur or submit, when the person has finished that field.
A sensible combination is: validate on submit for everything, validate on blur for fields the person has already visited and left, and re-validate a field that has already shown an error as the person fixes it, so the error clears promptly when corrected. That last rule is important: once an error is shown, the person deserves immediate confirmation that their fix worked, rather than having to submit again to find out. Do not validate a field on blur if the person has never typed in it and merely tabbed through it on the way to another field, because that creates errors for fields they have not yet attempted. Track whether a field has been touched, and only show errors for touched fields, except at submit time, when all fields are fairly checked.
Test timing by using the form badly on purpose. Type half an email and tab away, type a wrong value and correct it, submit an empty form, and fix errors one by one. At each step, ask whether the message appeared at a moment when the person could act on it, and whether it disappeared when the problem was fixed. A form that scolds early, stays silent when fixed, or waits until the end to mention a problem in the first field has a timing problem, and timing problems feel, to the user, like the form itself is rude.
Check: Why should error messages usually not appear on every keystroke?
Section 21 — Error messages that tell people how to fix it
A good error message does three things: it names the problem, it names the field, and it tells the person how to fix it. "Email address: enter an address with an at sign, such as jane@example.com" does all three. "Invalid input" does none of them, because it does not say which input, what is invalid about it, or what a valid answer looks like. "Error" alone is worse still, because it adds alarm without information. When you write an error message, imagine the person reading it is already annoyed, possibly on a phone, and wants one clear next action. Give them that action in the message itself, not hidden behind a link to a help page they may never open.
Placement is part of the message. An error should sit close to the field it describes, usually directly below the label and field, where the eye naturally goes after typing. An error at the top of the page alone forces the person to remember which field it referred to while scrolling back to find it. An error in a popup that disappears forces them to remember it while fixing. An error that replaces the help text is acceptable only if the help text is not also needed to fix the problem; otherwise, keep both, with the error clearly distinguished. Colour can highlight an error, but it must not be the only signal: add text, and where helpful, an icon with a text alternative, so the error is visible to people who cannot see the colour.
Tone matters as much as content. Error messages should be neutral and helpful, never blaming, joking at the person's expense, or using technical jargon. "Your password is wrong" accuses the person; "That password does not match our records. Try again or reset it" states the situation and offers a path. Avoid exclamation marks, capital letters for emphasis, and humour that may not translate or may feel mocking when someone is stuck. Avoid also revealing security details: a login error should not say whether the username or the password was wrong, because that information helps an attacker guess accounts. That security rule is an exception to the general rule of specificity, and it applies wherever revealing which part failed would help abuse.
Finally, test error messages with real mistakes, not just with the mistakes you expect. Leave a field blank, enter a value in the wrong format, enter a value that is too long, and enter a value that conflicts with another field. For each, read the message as a stranger would. Does it name the field? Does it say what is wrong? Does it say what to do? If any answer is no, rewrite it. Error messages are the form's customer service: most people will only read them when something has already gone wrong, and the quality of those messages decides whether they try again or leave.
Check: What three things must a good error message contain?
Section 22 — Inline errors versus error summaries
There are two places errors can appear: beside the field, called an inline error, and together at the top of the form, called an error summary. Both have a role, and the best forms use both, each doing a different job. Inline errors tell the person exactly which field is wrong and how to fix it, at the moment they are looking at that field. Error summaries tell the person, before they start fixing, how many problems there are and where they are, with links that jump to each problem field. A long form with only inline errors forces the person to hunt through the whole form to find every problem. A form with only a summary forces them to remember each problem while scrolling to fix it. Together, they cover both needs.
An error summary should appear at the top of the form, or at the top of the current step in a multi-step form, after a failed submission. It should have a clear heading, such as "There is a problem", followed by a list of links, one per problem, each naming the field and the problem in plain words. Each link should move focus to the corresponding field when activated, so keyboard and screen reader users can jump straight to the fix. The summary should not duplicate long explanations; a short problem statement with a link is enough, because the full instruction sits beside the field. Do not include problems that have already been fixed, and do not keep a stale summary visible after a successful resubmission.
Inline errors, meanwhile, should stay with their fields even when a summary is present. They are the detailed instruction, and they must remain visible until the field is fixed. When a field is fixed, its inline error should clear, and on the next submission, the summary should reflect only the remaining problems. A common bug is a summary that lists problems that no longer exist, because it was built once and never updated. Test this by fixing one of two errors and resubmitting: the summary should shrink to one item, and the fixed field should show no error. Test also by fixing all errors: the summary should disappear entirely, not linger as a confusing relic.
Accessibility decides the details. The summary should be announced when it appears, so a screen reader user knows the submission failed without having to discover it by scrolling. Focus should move to the summary heading on a failed submission, so the person can hear the list of problems and follow its links. Inline errors should be connected to their fields, a technique covered in the next section, so they are announced when the field receives focus. A form that shows errors only visually, without moving focus or announcing them, has not really shown them to everyone, and its users with assistive technology will be left guessing why nothing happened when they pressed submit.
Check: What job does an error summary do that inline errors alone cannot?
Section 23 — Making errors accessible
An error that is only visible is not accessible. For a screen reader user, an error message must be connected to its field, announced at the right time, and distinguishable from ordinary help text. The main tool for connection is aria-describedby, which lists the identifiers of elements that describe a field, such as its help text and its error message. When the field receives focus, the screen reader announces the label, then the descriptions, so the person hears the error in context. The aria-invalid attribute marks a field as invalid, so assistive technology can report its state without relying on colour or an icon. Together, these attributes turn a visual error into information a screen reader user can actually use.
Timing and announcement matter as much as connection. An error message that appears silently while the person is typing elsewhere may never be heard. For an error summary, use a live region or move focus to the summary, so its appearance is announced. For inline errors that appear after a failed submission, moving focus to the first problem field or to the summary is the reliable approach, because focus movement is announced by screen readers as a matter of course. Avoid announcing every keystroke change as a live update, which would interrupt typing with a stream of messages. Announce the result of an action, such as a submission, not every intermediate state.
Do not rely on colour, icons, or position alone to convey an error. A red border around a field is invisible to someone who cannot see colour, and an icon without a text alternative is silent to a screen reader. Every error needs words, and those words need to be reachable. That means the error text must be real text in the page, not text baked into an image, and it must not be hidden with styles that also hide it from assistive technology. Check this by testing with a screen reader if you can, or at least by inspecting the page structure: is the error element present, is it referenced by the field's described-by list, and is the field marked invalid? If any link in that chain is missing, the error is only half built.
Also preserve the person's work when an error is shown. A form that clears fields on a failed submission forces a screen reader user to re-enter everything, with no way to know what was lost, and it frustrates every other user too. Re-display the form with all values intact, errors connected, and focus in a sensible place. Test the whole error experience without a mouse, using only a keyboard and, if possible, a screen reader. If you can find every error, understand every fix, and resubmit successfully without sight or a mouse, the errors are accessible. If you cannot, fix the connection before you polish the wording.
Check: How does aria-describedby help a screen reader user understand an error?
Section 24 — Focus after an error or a success
Focus is where the keyboard and the screen reader are looking. After a failed submission, focus should go somewhere useful: either the error summary, so the person hears the list of problems, or the first field with an error, so they can fix it immediately. What it should not do is stay on the submit button, leaving the person to guess why nothing happened, or jump to the top of the page without explanation, where the person must scroll and hunt. Moving focus deliberately is a small act that makes the difference between a form that guides and a form that abandons the user at the moment of failure.
After a successful submission, focus needs equal care. If the page shows a confirmation message in place, move focus to that message's heading, so a screen reader user hears the success without having to search for it. If the form navigates to a new confirmation page, the new page's heading is the natural focus, and the browser will handle it as a new page load. If the form stays on the same page and simply clears, which is rarely the right choice, focus should go to a clear confirmation, not to an empty first field that suggests the submission never happened. A person who cannot tell whether their submission succeeded will often submit again, creating duplicates, and that confusion is a focus and feedback failure, not a user error.
Focus management also applies inside the form, when the form changes. If choosing an option reveals new fields, focus should stay where the person is, or move to the newly revealed content only if that content is the obvious next step and the move is announced. If a field is removed, focus must not vanish with it: move it to a sensible nearby element, not to the top of the page. If a dialog opens, focus must move into the dialog and stay there until it closes, returning to the element that opened it. These rules sound detailed, but they follow one principle: focus should always be somewhere the person expects, on something they can act on, and never lost in a place that no longer exists or that they cannot see.
Test focus by using the form with only a keyboard. Submit with errors and watch where the focus indicator goes. Fix the errors and submit again. Trigger any dynamic change and check that focus survives it. If you ever press Tab and cannot see where focus is, or if focus disappears entirely, the form has a focus bug, and it will affect keyboard users and screen reader users most, but it will confuse everyone. Visible focus, covered in other chapters, is part of this: moving focus is only helpful if the person can see where it landed.
Check: Where should focus go after a failed form submission, and why?
Section 25 — Success feedback and confirmation
A form that succeeds silently has not finished its job. After a successful submission, the person needs to know three things: that it worked, what happens next, and what to do if something is wrong. A confirmation message should say plainly, "Your application has been sent", not "Success" alone, which does not say what succeeded. It should say what happens next, such as "We will reply within three working days", only if that promise is true, and it should give a way to check or correct the submission, such as a reference, a summary of what was sent, or a contact route. A vague success message leaves the person wondering whether to wait, to check an inbox, or to submit again.
Show a summary of what was submitted where it helps. For an order, show what was ordered, the total, and the delivery details, so the person can spot a mistake while there is still time to fix it. For an application, show the key details and a reference the person can quote. For a message, show that the message was received, and whether a reply should be expected. Do not show sensitive details, such as a full card number or a password, in a confirmation, even to the person who submitted them, because confirmations may be seen by others, saved, or forwarded. Summarise safely: show the last few characters of an account identifier where that helps identification, and nothing more than is needed.
The confirmation should also be reachable and lasting. A message that appears briefly and then vanishes, or that only appears as a small toast in a corner, is easy to miss, especially for a screen reader user or someone distracted at the crucial moment. A dedicated confirmation page, or a prominent confirmation section that replaces the form, is more reliable, because it can be bookmarked, revisited, and read at leisure. If you use an inline confirmation, keep it visible until the person navigates away, move focus to it, and make sure it does not disappear on the next interaction. Send an email confirmation as well where the submission matters, and say in the on-screen confirmation that an email is on its way, so the person knows to look for it.
Finally, prevent the duplicate-submission trap. After a successful submission, the form should not remain in a state where pressing submit again, refreshing, or pressing back and forward resends the same data. The usual solution is to navigate away from the form after success, or to replace it with the confirmation, so there is no submit button left to press twice. Test this by submitting, then refreshing, then pressing back and forward. If any of those actions creates a duplicate, the success handling is incomplete, and the confirmation, however well worded, is covering for a bug.
Check: What three things must a success message tell the person?
Section 26 — Preventing double submissions
Double submission happens when a person presses submit twice, or when a slow network makes them think the first press did nothing, and the same order, message, or application is sent twice. Preventing it is a front-end courtesy and a back-end necessity, but the front end can do a great deal. The simplest step is to disable the submit button immediately after the first press, and change its label to show progress, such as "Sending…" or "Please wait". That visible change tells the person their press was received, which removes the main reason people press twice: uncertainty. Without that feedback, even a fast form can feel unresponsive on a slow connection, and a person will reasonably press again.
Disabling the button must be done carefully. If the submission fails, the button must be re-enabled, with its original label restored, and the error shown, so the person can fix the problem and try again. A button that stays disabled after a failure traps the person: the form looks broken, and the only escape is to reload and lose their answers. Test this cycle: submit with a forced failure, such as a network error, and check that the button returns to a usable state with the form's data intact. Also make sure the disabled state is visible, not just a technical attribute: a button that looks active but does nothing is as confusing as one that looks disabled but still works.
Beyond the button, guard against duplicate submissions at the level of the action. Pressing Enter in a text field can submit a form, and a person who presses Enter twice quickly, or who refreshes after a successful submission, can trigger a repeat. Navigating to a confirmation page after success, as described in the previous section, removes the resubmission path for the common case. For the remaining cases, the server must protect itself, for example by recognising a repeated request and treating it as the same submission rather than a new one. Front-end developers should ask back-end colleagues how duplicates are handled, rather than assuming a disabled button is sufficient, because a disabled button can be bypassed and does not survive a page reload.
Also consider the person's perspective when a duplicate does occur. If an order is placed twice, the confirmation should make the duplication visible, and there should be a clear route to cancel or correct it. A system that silently accepts duplicates and leaves the person to discover them on a statement has failed at the last step. Test double submission deliberately: press submit twice quickly, submit and refresh, submit on a slow connection. If any path creates a duplicate without a clear warning or recovery, fix it before release, because duplicates are one of the most expensive form failures, in money, in support time, and in trust.
Check: What must happen to a disabled submit button if submission fails?
Section 27 — Multi-step forms and progress
A multi-step form breaks a long task into a sequence of screens, each asking for one group of related answers. The benefit is psychological as much as practical: a person who sees twenty fields at once may give up, while the same twenty fields spread over four steps, each with a clear heading, feel manageable. The risk is that steps hide progress and trap answers. A multi-step form must always show where the person is, how many steps remain, and how to go back without losing work. A progress indicator at the top, such as "Step 2 of 4: Delivery address", with the step names listed where space allows, gives that orientation. Without it, the person is walking through rooms with no sense of how many remain.
Each step should be a coherent group, not an arbitrary slice. Group by the person's mental model, as in the grouping section: personal details, then address, then payment, then review. Do not split a single idea across two steps, such as asking for a street address on one step and its postcode on the next, because that forces the person to hold an unfinished idea across a screen change. Do not put a trivial step alone, such as a single checkbox on its own screen, because that wastes a click and feels like padding. The final step should almost always be a review step, where the person can see everything they entered, correct any of it, and confirm before submitting. A review step catches mistakes that inline validation cannot, because it lets the person read their answers as a whole, in context.
Going back must be safe. A back button on each step, and browser back support where possible, should return the person to the previous step with all answers intact. A form that loses answers on back is punishing the very behaviour — checking and correcting — that leads to accurate submissions. Similarly, validation on each step should only check that step's fields, not the whole form, because complaining about a later step the person has not reached is confusing. When a step is completed, save its answers, whether in the browser or on the server, so that a refresh, a dropped connection, or an accidental navigation does not erase progress. Draft saving is covered in the next section.
Test a multi-step form as a journey, not as isolated screens. Start at the beginning, go forward, go back, change an early answer, and check that later steps still make sense. Refresh in the middle and check that progress survives. Complete it on a phone, where each step change is a full screen replacement, and check that the progress indicator remains visible and accurate. A multi-step form that feels like a guided walk, with signposts, a way back, and a final review, will be completed more often and more accurately than a single long form, but only if those signposts and safeguards are actually built.
Check: Why should the last step of a multi-step form usually be a review step?
Section 28 — Saving drafts and autosave
Losing a half-filled form is one of the most demoralising experiences on the web, and it is largely preventable. Draft saving keeps a person's answers as they type, so that an interruption, a crash, a dead battery, or an accidental navigation does not erase their work. The simplest form of draft saving stores answers in the browser, so that returning to the same form on the same device restores them. A stronger form saves to the server, so that the person can continue on another device, but that requires an account or an identifier, and it raises privacy questions about storing unfinished personal data. Choose the level that fits the form's length and sensitivity, and be honest about it in the interface.
Autosave must be visible but not intrusive. A small, quiet indicator, such as "Draft saved" with a time, tells the person their work is safe without interrupting them. Do not show a popup on every save, and do not move focus or scroll the page when saving. Save on a sensible trigger: when a field loses focus, or after a short pause in typing, rather than on every keystroke, which can be wasteful and can cause flicker. When the person returns, restore the draft and say so plainly: "We restored your draft from earlier. You can continue where you left off, or start over." That message matters, because a restored form that appears without explanation can confuse a person who expected a blank form, or who shares the device with someone else.
Privacy and control are part of draft saving, not an afterthought. A draft may contain sensitive personal information, so it should be stored securely, cleared when the form is successfully submitted, and cleared when the person chooses to discard it. Provide a clear "Clear draft" or "Start over" action, and do not restore a draft onto a shared or public device without care. On a login form or a payment form, draft saving of secrets is inappropriate: never autosave passwords or full payment details, and be cautious with any field that would embarrass or endanger the person if another device user saw it. If in doubt, save less, and say what you save.
Test draft saving by simulating real interruptions. Fill half a form, close the tab, reopen it, and check what returns. Fill a form, submit it successfully, and check that no stale draft reappears on the next visit. Fill a form on one device and, if server drafts are promised, check that it appears on another. A draft feature that works in the demo but fails after a real interruption is worse than no draft feature, because it teaches people to trust a safety net that is not there. When it works, it quietly removes one of the biggest reasons people abandon long forms.
Check: What should a form say when it restores a saved draft?
Section 29 — File uploads without frustration
File uploads look simple — a button, a file, a submit — but they fail in more ways than most form fields. The first failure is ignorance: the person does not know what kinds of files are accepted, how large they may be, or how many they may send, until after they have chosen a file and been rejected. State all three before the person chooses: accepted types in plain words, such as "PDF or image, up to 5 MB", the maximum number of files, and any requirement such as a clear photo of a document. That information belongs beside the upload control, not in an error message after the fact. A file input that accepts the wrong type silently and only complains on submit has wasted the person's effort in finding the file.
The second failure is invisibility. After choosing a file, the person should see its name, its size, and, where helpful, a thumbnail or a confirmation that it was received. They should be able to remove it and choose another without resetting the whole form. If the upload takes time, show progress honestly: a progress indicator, a percentage, or at least a "Uploading…" state that prevents a second submission. On a slow connection, a large file may take a long time, and a form that shows nothing during that time invites the person to press submit again, navigate away, or assume the upload failed. Never let a file upload block the rest of the form without explanation.
Accessibility and device differences matter. A file input must be reachable by keyboard and labelled like any other field, and its button text should be clear. On a phone, the file chooser may offer the camera, the photo library, or files, and the accept attribute can hint at the right source, such as images, but it must not be so restrictive that it blocks a legitimate file. Test uploads on a phone and on a desktop, with a file that is too large, a file of the wrong type, and a file with a long or unusual name. Each case should produce a clear, specific message, and the rest of the form's answers should survive the failure.
Finally, treat uploaded files as untrusted data on the server, and never promise on the front end that a file is safe or suitable merely because its extension matches. The front end can check size and type as a courtesy, to give fast feedback, but the server must check again, because extensions can be faked. Tell the person what will happen to their file: how long it will be kept, who will see it, and whether they can delete it later. An upload is an act of trust, and the form should repay that trust with clarity before, feedback during, and confirmation after.
Check: What three facts about an upload must be stated before a person chooses a file?
Section 30 — Search forms and filters
A search form has a different job from most forms: it does not collect information to store, it asks a question and returns answers. Its design should therefore favour speed and forgiveness over completeness. A single search box, clearly labelled "Search", with a submit button that says "Search", is often all that is needed. Do not clutter a search form with advanced fields that most people will never use; put advanced options behind a clear link or toggle, so the simple path stays simple. The search box should be wide enough for a real query, should preserve the query after searching so the person can refine it, and should handle empty searches gracefully, by showing help or popular options rather than an error that scolds the person for pressing search too soon.
Filters are search's companions, and they need the same care. Each filter should be clearly labelled, its options should be real values that exist in the results, and applying a filter should not erase the search query or other filters. Show how many results each filter would give where that is possible, because a filter that leads to zero results without warning wastes a click and confuses the person about whether the filter or the search failed. When a combination of filters gives no results, say so plainly, explain which filters are active, and offer a one-click way to clear them, rather than leaving the person staring at an empty page wondering what went wrong.
Search feedback matters. While results load, show a loading state so the person knows the search is working. When results arrive, show how many there are, and highlight or summarise why they matched, where that helps. When there are no results, do not show a blank page: suggest a broader query, check spelling gently, or offer related options. A "no results" page is a form of error message, and it should follow the same rules as other errors: name the problem, explain it, and offer a next step. Also preserve the search in the URL, as discussed under GET, so results can be shared and revisited, and so the back button returns to the previous search rather than to an empty box.
Test search forms with real queries, including misspellings, very short queries, very long queries, and queries with special characters. Check that the query survives a search, a filter change, and a back-button press. Check that the form works with a keyboard and a screen reader, and that its results are announced sensibly. A search form that feels instant, forgiving, and easy to refine will be used far more than one that demands a perfect query on the first try, because searching is an act of exploration, not of form-filling, and the interface should respect that difference.
Check: Why should a search box preserve the query after searching?
Section 31 — Checkout forms and payment fields
Checkout is where form design directly affects money, and where mistakes cost sales and trust. The core principle is to ask for payment details only when they are needed, in the order a person expects, and with the least possible friction. Show the order summary beside or above the payment fields, so the person can confirm what they are paying for without leaving the form. Show the total clearly, including any delivery cost and tax, before the payment button, because a total that changes after payment feels like a trick. The payment button itself should say what it does, such as "Pay now", with the amount, rather than a vague "Submit" that leaves the person wondering whether they are about to be charged.
Payment fields deserve special handling. A card number field should accept spaces, group digits for readability, and use an input mode that brings up a numeric keyboard, while storing the value as text so spaces and formatting do not corrupt it. An expiry field should accept both common formats and explain which is expected, or use separate month and year fields that are clearly labelled. A security code field should explain where to find the code, with a small diagram or description, because many people do not know the term. Never store, log, or display a full card number on the front end, and never build your own card handling when a reputable payment provider's hosted field or component is available: handling card data directly brings security and compliance duties that a front-end form alone cannot satisfy.
Checkout also needs to handle addresses, delivery choices, and contact details without duplicating effort. If the billing address is usually the same as the delivery address, offer a single checkbox for that, checked sensibly, rather than forcing the person to type the same address twice. If a delivery choice affects the total, update the total immediately and visibly when the choice changes, so there is no surprise at payment. If an email address is needed for a receipt, say so, and do not use that receipt address for marketing without separate, explicit consent. Each of these small decisions reduces abandonment, because checkout abandonment is often caused not by price, but by a form that feels long, confusing, or untrustworthy at the final step.
Finally, checkout must handle failure gracefully. A declined payment is not a user error to scold, and it may have nothing to do with what the person typed. Show a neutral message, preserve all non-payment answers, let the person try another payment method without retyping their address, and do not charge twice when they retry. Test checkout with a declined payment, a slow connection, and a back-button press after payment, and check that no duplicate charge or lost order results. A checkout form that is clear before payment, honest about the total, and kind after a failure earns the trust that makes people return, while one that hides costs or punishes a decline loses it in a single transaction.
Check: Why should the total, including delivery, be shown before the payment button?
Section 32 — Address forms that respect real addresses
Address forms are a classic source of frustration, because addresses do not follow one universal shape. A form designed for one country's addresses will fail people from elsewhere: it may demand a postcode where none exists, force a state or province where the concept does not apply, or require a house number in a place where addresses are described by landmarks. The first rule of address forms is therefore to make only the genuinely universal parts required, and to adapt the rest to the country chosen. When the person selects a country, the address fields should adjust: the label for the region field should change to the local term, the postcode field should be optional where postcodes do not exist, and the validation should match that country's format, not a single global pattern.
Field order should follow local convention where possible, or at least follow a logical order that the person can follow without thinking: the most specific part first or last, consistently, and with clear labels for each part. Splitting an address into many small fields — house number, street, district, city, region, postcode — gives cleaner data for a system, but it forces the person to slice their address into your boxes, which they may do differently. A single textarea for a full address, or a smaller number of flexible fields, is often kinder, especially for international users, even if it requires more work on the back end to parse. The trade-off is real: structured fields help delivery and sorting, while free text helps the person. Where delivery accuracy matters, structured fields with local adaptation are justified; where it does not, do not impose structure for its own sake.
Autocomplete for addresses, where a person starts typing and the form suggests complete addresses, can save a great deal of typing, but it must be offered, not imposed. A person should be able to ignore a suggestion and type their address manually, and a manual entry path must always exist, because autocomplete services do not cover every address, especially new buildings, rural areas, and addresses in less mapped regions. When a suggestion is chosen, show the full address that will be used, so the person can check it, and let them edit it afterwards. An address that is silently replaced by a suggestion the person did not verify is a delivery failure waiting to happen.
Test address forms with addresses from several countries, including ones without postcodes, ones with long region names, and ones where the street name comes after the house number. Check that the form does not reject a valid address because it does not fit a narrow pattern, and that it does not force a person to invent a value for a field that does not apply to them. An address form that respects real addresses will collect fewer invented postcodes, fewer "N/A" entries in required fields, and fewer failed deliveries, because it asked for the address the person actually has, not the address the designer imagined.
Check: Why should address fields adapt when the country changes?
Section 33 — Consent, terms and honest checkboxes
Consent checkboxes are legal and ethical signals, not just form fields, and they must be treated as such. A checkbox that says "I agree to the terms" is only meaningful if the person can actually read the terms, understands what they are agreeing to, and chooses freely. Link the terms from the label itself, so the person can open them without losing the form, and keep the label short while the linked document carries the detail. Do not pre-check a consent box: a pre-checked box records agreement the person never gave, and in many contexts it is not valid consent at all. The person must take a deliberate action to agree, and the form must record that action, not assume it.
Separate different kinds of consent. Agreeing to terms of service is not the same as agreeing to receive marketing emails, and agreeing to one must not silently imply agreement to the other. Give each consent its own checkbox, with its own plain-language label: "I agree to the terms of service" and, separately, "Send me occasional updates about new features. I can unsubscribe at any time." The second label does two jobs: it says what will be sent, and it says the person can stop it. That honesty increases trust, and it usually increases genuine signups, because people who understand what they are agreeing to are less likely to mark the messages as spam later. Never bundle marketing consent into a required terms checkbox, and never make marketing consent a condition of using a service that does not need it.
The wording of consent labels matters. Avoid legal jargon in the label itself, and avoid vague phrases such as "I agree to everything" or "I accept all conditions", which do not tell the person what "everything" includes. If a consent covers data sharing with third parties, say so, and name the purpose. If a consent is for a child's account or for health data, the stakes are higher, and the form should be even clearer, with a path to withdraw consent that is as easy as giving it. A form that makes consent easy to give and hard to withdraw is not obtaining consent; it is trapping it.
Test consent flows as a stranger would. Can you find the terms? Can you agree to terms without agreeing to marketing? Can you proceed without marketing consent? Is an unchecked required consent box reported as a clear error, naming the agreement, rather than a generic "complete all fields" message? If any answer is no, the consent design is misleading, however tidy it looks. Consent is one area where front-end convenience must never override honesty, because the checkbox is the record of a person's choice, and a choice that was not freely and knowingly made is not a choice at all.
Check: Why must a consent checkbox never be pre-checked?
Section 34 — Bots, spam and friction that respects humans
Every public form attracts automated submissions, from spam to outright abuse, and some defence is needed. The challenge is to add that defence without punishing real people. The worst approach is a puzzle that is hard for humans and easy for modern bots, or a test that blocks people with disabilities, people on slow connections, or people using assistive technology. A classic image puzzle that asks the person to identify objects in pictures, for example, is inaccessible to blind users unless an audio alternative is genuinely usable, and it is frustrating for everyone else. Before adding any bot defence, ask whether the form truly needs it, and whether a quieter defence would do.
Quieter defences start with the server. Rate limiting, which restricts how many submissions can come from one source in a short time, stops bulk abuse without bothering a normal user. Checking the submission on the server for patterns typical of bots, such as impossibly fast completion or fields filled in ways a human would not, can also help, provided it does not reject real people who fill forms quickly or use autofill. A honeypot field, a field hidden from humans but visible to simple bots, is a front-end technique that can catch naive automation, but it must be hidden in a way that does not trap screen reader users: a field hidden only visually may still be announced to a screen reader, so it must be hidden from assistive technology as well, and it must never be a field a human would need. These defences are imperfect, and they should be layered, not relied on alone.
When a visible challenge is unavoidable, choose one that respects the person. A simple, accessible challenge, with a clear alternative for people who cannot complete it, is better than a hard puzzle with no alternative. Explain why the challenge is there, in plain words, and do not require it on every submission if it is only needed for suspicious traffic. Do not use a challenge as a substitute for server validation: a bot that passes the challenge still submits data that the server must check, and a human who fails the challenge should be given another chance, not locked out. Also consider the cost in trust: a form that interrogates every visitor as a suspected bot tells honest visitors they are not trusted, and some will leave rather than prove themselves.
Test bot defences with the people they are most likely to harm: a screen reader user, a keyboard-only user, a person on a slow mobile connection, and a person who uses autofill. If any of them cannot complete the form, the defence is too costly, however effective it is against bots. The goal is a form that is easy for humans and hard for abuse, not a form that is hard for everyone. When in doubt, start with quiet server defences, measure whether abuse actually occurs, and add visible friction only where the evidence shows it is needed.
Check: Why is a visual puzzle a poor first defence against bots?
Section 35 — Forms on phones: thumbs, keyboards and small screens
A form that works on a desktop may fail on a phone for reasons that have nothing to do with the questions asked. The screen is narrow, the keyboard covers half of it, the person may be using one thumb, and the connection may be slow or intermittent. Designing for phones is therefore not a smaller version of desktop design; it is a different set of constraints, and it should be tested first, not last. Start with a single column, large tap targets, and fields that are tall enough to tap without precision. A field that is comfortable with a mouse can be painfully small with a thumb, and a button placed too close to another control will be tapped by mistake.
Keyboards are part of the phone form, as covered earlier, but the interaction between the keyboard and the page needs attention too. When the keyboard opens, it can cover the submit button, the error message, or the next field, leaving the person unsure what happened. The page should scroll so the active field and its feedback remain visible, and error messages should appear where they can be seen without dismissing the keyboard. Test this on a real phone, not just in a desktop browser's device simulation, because simulations do not always reproduce keyboard behaviour accurately. Also test in both portrait and landscape orientations, since a landscape keyboard covers even more of the screen.
Phone users also rely heavily on autofill, paste, and camera features. A form should accept pasted values, including values pasted with spaces or formatting, and should not clear a field when the person switches apps to copy a code or a number. A one-time code field should accept a pasted code in full, and ideally handle a code that arrives by message with a single tap, where the platform supports it. A file upload on a phone should offer the camera where that makes sense, such as for a photo of a document, but must also offer the file library, because not every file is a new photo. Each of these conveniences removes a step that, on a phone, feels much larger than it does on a desktop.
Finally, respect the phone's context. A person filling a form on a phone may be interrupted by a call, a message, or a loss of signal. Draft saving, covered earlier, matters more here than on a desktop, because interruptions are more frequent. A form that loses progress when the browser is backgrounded, or that times out quickly and discards answers, will be abandoned. Keep sessions generous where security allows, save drafts quietly, and let the person resume without starting over. A phone form that respects thumbs, keyboards, interruptions, and slow networks is not a compromised desktop form; it is a form designed for where most people actually are.
Check: Why must a phone form be tested with the keyboard open?
Section 36 — Responsive form layout that does not break
A responsive form adapts to the width available without breaking its meaning. The simplest responsive rule is to stack fields on narrow screens and allow careful side-by-side pairs only on wide screens, where there is room for both fields and their labels, help text, and errors. That rule should be driven by content, not by device names: a field pair that needs a certain width to be usable should stack below that width, whatever the device is. Use flexible widths, not fixed pixel widths that overflow a small screen or leave a form cramped on a large one. A form that scrolls horizontally on a phone, or that requires zooming out to see a whole field, has a responsive failure, not a minor styling issue.
Large text sizes are a responsive case too. A person who increases the browser's text size, or uses a device setting for larger text, should still be able to use the form. Labels should wrap, fields should grow, and buttons should not clip their text. Test the form at twice the normal text size and check that no label overlaps its field, no button text is cut off, and no error message disappears. A form that only works at one text size is not responsive; it is fragile. The same applies to zoom: a person who zooms the whole page to read it should not find that the form's layout collapses or that fields overlap.
Spacing is part of responsiveness. On a wide screen, generous spacing between fields helps the eye group labels with their fields. On a narrow screen, spacing must still separate groups clearly, without wasting so much vertical space that the form feels endless. Keep the relationship between a label, its field, its help text, and its error message tight, so they read as one unit, and keep the gap between units larger, so the units do not blur together. That rhythm — tight inside a field group, looser between groups — works at any width, and it helps a person scanning the form to understand its structure without reading every word.
Test responsiveness by resizing the browser continuously, not just at two or three preset widths, and watch for the points where the layout strains: a label that wraps awkwardly, a pair of fields that squeezes too narrow, a button that wraps onto two lines in a way that looks broken. Fix those strain points with a layout change, such as stacking earlier, rather than with a smaller font, which would punish the people who need larger text most. A responsive form is one where the questions remain clear and the answers remain easy at every width, from a small phone to a large monitor, and that clarity is worth more than any clever multi-column arrangement.
Check: Why should responsive breakpoints be based on content width, not device names?
Section 37 — Prefill, defaults and the danger of guessing
Prefill fills a field with a value you already know, such as an email address from a previous step, a country from a previous choice, or a name from an account. Done well, it saves typing and reduces errors. Done carelessly, it records a guess as if it were the person's answer. The difference is verification: a prefilled value should be visible, easy to check, and easy to change, and the person should be expected to confirm it before submitting. A prefilled value hidden in a collapsed section, or filled in a way that looks like a placeholder, is not a convenience; it is a trap, because the person may submit without noticing it, and the system will then act on a value they never approved.
Defaults are similar but broader: a default is a value chosen for the person when they have not chosen one, such as a default delivery option, a default language, or a default checkbox state. A default is honest when it reflects the most common, least harmful choice, and when changing it is easy. It is dishonest when it benefits the form owner at the person's expense, such as a default that signs the person up for marketing, or a default that selects a more expensive option. The test is simple: if the default were removed and the person had to choose, would they usually choose the same thing? If not, the default is steering, not helping, and it should be removed or made into an explicit choice.
Prefill also raises privacy questions. A field prefilled with personal data on a shared device reveals that data to anyone who opens the form, and a field prefilled from a previous session may reveal data the person thought was gone. Do not prefill sensitive fields, such as payment details or passwords, and do not prefill a form on a shared or public device without a clear reason. When a person clears a prefilled value, respect that choice and do not refill it on the next visit. When a prefilled value is wrong, the correction should be easy and should not trigger a confusing error about a value the person did not enter.
Test prefill by arriving at the form in different ways: as a returning user, as a new user, after a failed submission, and after a back-button press. In each case, check which fields are filled, whether the values are correct, and whether the person can change them without confusion. Check also that a prefilled form still validates correctly: a prefilled value that fails validation, because it is in an old format, will block submission with an error about a field the person never touched, which feels deeply unfair. Prefill is a promise that you already know something; keep that promise accurate, visible, and easy to correct.
Check: What makes a prefilled value a trap rather than a convenience?
Section 38 — Reset buttons and why they usually harm
A reset button clears every field in a form back to its initial values. It sounds helpful, as a way to start over, but in practice it is one of the most harmful controls a form can offer. The harm comes from its position and its irreversibility. A reset button is usually placed beside the submit button, where a person aiming for submit can tap it by mistake, especially on a phone. One mistap then erases minutes of careful typing, with no undo, and the person must start again or abandon the form. The benefit of a reset button — saving the effort of clearing fields one by one — is tiny compared with that cost, because people rarely want to clear an entire form, and when they do, they can reload the page or clear fields individually.
If a form genuinely needs a way to start over, such as a long application where the person might want to discard a draft, that action should be separate from submit, clearly labelled as a destructive action, and confirmed before it acts. A link or button that says "Clear all answers" or "Start over", placed away from submit, with a confirmation step that explains what will be lost, is far safer than a reset button beside submit. The confirmation should also offer to save a draft first, where draft saving exists, so that starting over is a choice, not an accident. For most short forms, even that is unnecessary: the person can simply leave the page, and the form's job is to not trap them into losing work.
The technical reset behaviour also has quirks. A reset returns fields to their initial values, not necessarily to empty: a prefilled field returns to its prefilled value, and a checkbox returns to its initial checked state. That behaviour can surprise a person who expected "clear" to mean "empty", and it can reintroduce a default they had deliberately changed. If you must implement a clear action, test it with prefilled and defaulted fields, and make its result match its label: if it says "Clear all", it should clear all, not restore defaults. Better still, avoid the control entirely and let the person clear fields one by one, which is slower but never catastrophic.
The general principle is that destructive actions should be hard to do by accident and easy to undo, while constructive actions, such as submitting, should be easy to do on purpose. A reset button reverses that principle: it makes destruction easy and undo impossible. Remove it from your forms unless you have a specific, tested reason to keep it, and if you keep it, move it away from submit, label it as destructive, confirm it, and provide a way back. Most forms are better without it, and their users are safer for its absence.
Check: Why is a reset button beside submit especially dangerous?
Section 39 — Measuring forms without spying on people
Measuring a form means learning where people struggle, so you can fix it. Useful measures include how often a form is started and completed, which fields produce the most errors, how long each step takes, and where people abandon a multi-step form. Those measures point to real problems: a field with a high error rate may have unclear help text, a step with high abandonment may be too long or ask for sensitive information too early, and a form with a low completion rate may be asking for too much. Measuring is therefore part of good form design, not an optional extra, provided it is done honestly and with respect for privacy.
Honest measurement respects the person. It does not record the contents of fields, especially sensitive fields such as passwords, payment details, health information, or free-text messages, even in anonymised form, because field contents are personal data and their collection creates risk without a corresponding benefit for the measurement question. It does not track individuals across forms or sites without their knowledge, and it does not use measurement as a cover for marketing profiling. Aggregate counts — how many people reached a step, how many saw an error on a field — are usually enough to find problems, and they can be collected without storing who did what. If a measure requires more detail, ask whether the improvement it would enable justifies the privacy cost, and document that decision.
Use measurements to make specific changes, not to chase a single number. A completion rate that rises because you removed a necessary field is not an improvement; it is a loss of information. A field error rate that falls because you loosened validation so much that bad data passes is not an improvement either. Pair quantitative measures with qualitative checks: watch a few people use the form, read support messages about it, and test it yourself with edge cases. Numbers tell you where to look; people tell you why. A form team that only watches numbers may optimise for completion at the cost of accuracy, trust, or accessibility, and that trade is rarely worth it.
Finally, be honest about what measurement cannot prove. A change that coincides with a rise in completions may have been caused by something else, such as a seasonal change or a different audience, and claiming a precise causal effect without evidence is misleading. Report measurements with their context: the period, the audience, and the change made. That honesty protects the team from chasing noise, and it protects users from being treated as data points rather than people. Measure to help people complete forms accurately and comfortably, and stop measuring anything that does not serve that purpose.
Check: Why should form measurement never record field contents?
Section 40 — Testing a form like a sceptical user
Testing a form means trying to break it in the ways real people will, not just confirming that the happy path works. The happy path — filling every field correctly and submitting — is the least informative test, because it is the path the designer already imagined. Sceptical testing asks what happens when the person does everything else: leaves fields blank, enters nonsense, pastes text with extra spaces, uses autofill, submits twice, goes back, refreshes, loses connection, uses only a keyboard, zooms the text, or uses a screen reader. Each of those behaviours is normal, and a form that only works for the careful, mouse-using, fast-connection user is not finished.
Build a checklist for each form and run it before release. Submit empty, submit with only required fields, submit with optional fields blank and filled, trigger each error and fix it, test back and forward navigation, test refresh after success and after failure, test on a phone with the keyboard open, test with JavaScript disabled if a fallback is promised, and test with a screen reader or at least with a keyboard alone. Check that data survives errors, that focus goes somewhere sensible, that error messages are specific, and that success is confirmed clearly. Record the results, fix the failures, and retest the fixes, because a fix for one case can break another, such as a validation change that now rejects a valid answer.
Also test with real content, not just with placeholder examples. Use long names, names with accented characters, addresses from different countries, email addresses with plus signs, and messages with paragraphs and special characters. Use the longest realistic answer for each field and check that the layout, the character count, and the server all handle it. Use the shortest realistic answer and check that it is not rejected for being too brief. Content that is realistic reveals assumptions that test data hides: a name field that assumes two parts, a postcode pattern that assumes one country's format, or a message limit that cuts off a normal paragraph.
Finally, test with people who are not the designer. Ask someone unfamiliar with the form to complete it while you watch without helping, and note where they hesitate, misread, or ask a question. Those hesitations are the form's real errors, even if no technical error occurred. A form that passes automated checks but confuses a real person still needs work, and a form that a stranger can complete without help, on a phone, with errors handled kindly, is ready to be trusted with real submissions. A sceptical tester also checks the form after a change: a new validation rule, a renamed field, or a redesigned layout can break a path that previously worked, so regression testing matters as much as first testing. Keep a short written checklist for each form and rerun it whenever the form changes, rather than trusting memory that the happy path still covers everything.
Check: Why is testing only the happy path not enough for a form?
Section 41 — Button labels are instructions
A button's label is an instruction, and it should say what will happen when the button is pressed, in a verb that matches the action. "Send message", "Create account", "Save changes", and "Pay now" all tell the person what the button does. "Submit", "OK", and "Click here" do not, because they describe the mechanics of pressing a button, not the outcome. A person scanning a form should be able to tell, from the button alone, what the next step is, and whether it is safe to press it. That clarity matters most at the final step, where pressing the button may charge money, send an application, or publish something, and where a vague label creates doubt at exactly the moment confidence is needed.
Button labels should also reflect the state of the action. While a submission is in progress, the label should change to show that, such as "Sending…" or "Creating your account…", and the button should be disabled to prevent double submission, as covered earlier. When the action is complete, the button should not remain as a trap for a second press; the form should move to a confirmation. When a button is not the main action, its label should make that clear too: "Save draft" is not the same as "Publish", and "Cancel" is not the same as "Go back". A cancel button that discards work should say so, or be confirmed, rather than silently destroying answers. The distinction between primary and secondary actions should be visible in both wording and styling, with the primary action most prominent.
Avoid button labels that promise something the button does not do. A button that says "Get started free" but leads to a payment form is misleading, and a button that says "Download" but actually signs the person up for a newsletter is deceptive. The label is a promise, and breaking it, even once, damages trust in every other label on the site. Similarly, avoid labels that use jargon the audience may not know, or that assume a technical step the person cannot see. "Authenticate" is less clear than "Sign in", and "Proceed" is less clear than "Continue to payment", because the second version names the destination. When in doubt, write the label as a sentence the person would say about their own goal: "I want to send this message" becomes "Send message".
Test button labels by reading them out of context. Show someone just the buttons from a form, without the rest of the page, and ask what each one does. If they cannot tell, the label needs work. Also test the labels on a phone, where a long label may wrap or be cut off, and with a screen reader, where the button's accessible name is the label the person hears. A button label that is clear, specific, honest, and state-aware is a small piece of writing with a large effect: it turns the moment of submission from a leap of faith into a confident next step.
Check: Why is "Submit" a weaker button label than "Send message"?
Section 42 — Help text, hints and microcopy
Microcopy is the small text around a form: help text under a field, hints beside a label, explanations for why information is needed, and short reassurances. It is small, but it carries a large share of a form's usability, because it answers the questions people ask silently as they fill a form: what format do you want, why do you need this, what will happen to it, and what if I do not know? Good microcopy answers those questions before they become errors. It sits close to the field it explains, it is written in plain language, and it stays visible while the person types, unlike placeholder text. A field with good microcopy rarely needs an error message, because the person understood the task before attempting it.
Help text should be specific and brief. "Enter your postcode as it appears on your address, for example SW1A 1AA" helps; "Enter a valid postcode" does not, because it repeats the requirement without explaining it. "We need a phone number only if there is a problem with your delivery" explains the reason and the use, which makes the person more willing to provide it. "Your password must be at least twelve characters" states a rule before the person tries to break it. Each piece of help text should earn its place: if it states the obvious, such as "Enter your name" under a field labelled "Name", it adds noise, not help, and it should be removed. If it answers a real doubt, keep it, even if it makes the form slightly longer, because a slightly longer form that is understood beats a shorter form that confuses.
Microcopy also includes tone. The words around a form set its relationship with the person: formal or friendly, reassuring or demanding. A consistent, respectful tone — plain, direct, and free of blame — works for most forms. Avoid humour in error messages and in sensitive contexts, such as health, money, or legal agreements, where a joke can feel dismissive. Avoid also the false friendliness that masks a demand, such as "We just need a little more from you!" above a long list of required fields. People can tell when friendliness is a coating over friction, and it does not make the friction feel smaller. Honesty in microcopy — saying what is needed, why, and what happens next — builds more goodwill than cheerful wording over an unclear form.
Test microcopy by removing it and seeing what breaks. If a field becomes ambiguous without its help text, the help text is essential and should stay, and the label may also need strengthening. If a field remains clear without it, the help text may be noise. Test also with translation and large text in mind: microcopy that only fits in a short English sentence at one size will break when translated or enlarged, so keep it concise and let it wrap gracefully. Microcopy is not decoration around the form; it is the form's voice, and a clear voice is what turns a set of boxes into a conversation a person can follow.
Check: What question should each piece of help text answer for the person?
Section 43 — Plain language in forms
Plain language means writing so that the intended audience can understand the form on first reading, without needing a dictionary, a legal background, or a second attempt. It is not dumbing down; it is respecting the reader's time and attention. In forms, plain language means short sentences, common words, active verbs, and concrete examples. "Enter the name on your account" is plain; "Provide the nomenclature associated with the account holder" is not, even though it says the same thing in a technical register. The second version forces the person to translate before they can answer, and translation is work that the form should have done for them.
Plain language also means avoiding jargon that the audience may not share. Terms such as "credentials", "authentication", "verification", and "identifier" are familiar to developers but opaque to many users. Where a technical term is unavoidable, explain it the first time it appears, in the same sentence if possible: "Enter the code we sent to your phone. This code proves it is really you." That pattern — term, then explanation — lets the person learn the term without being blocked by it. Avoid also abbreviations without expansion, such as "DOB" for date of birth, which some people will not recognise, and avoid Latin phrases and legal shorthand in labels and help text, reserving precise legal wording for the linked documents where it belongs.
Sentence structure matters too. A form label or help text should usually be one idea per sentence, with the main point first. "Your password must be at least twelve characters. You can use spaces." is clearer than a single long sentence that buries the length rule inside a clause about security policy. Lists help where several rules apply: a short list of password rules is easier to scan than a paragraph containing the same rules. Numbers help as well: "within three working days" is more concrete than "shortly", and "up to 5 MB" is more useful than "not too large". Concrete language lets the person judge whether they can comply before they try, which reduces errors and frustration.
Test plain language by reading the form aloud to someone outside the team, or by asking a stranger to paraphrase each label and help text in their own words. If they paraphrase it differently from what you intended, the wording is ambiguous, however correct it sounds to the team. Also test with translation in mind, since plain, concrete language translates more reliably than idiom, humour, or complex sentences. A form written in plain language is not just kinder; it is more accurate, because it reduces the gap between what the designer meant and what the person understood, and that gap is where most form errors begin.
Check: Why is "Provide the nomenclature" worse than "Enter the name" on a form?
Section 44 — Empty states, no results and waiting states
A form is not only its fields; it is also the states around them, and those states need writing too. An empty state is what a person sees when a form or a list has no content yet, such as a saved-addresses list with no addresses, or a drafts list with no drafts. A good empty state explains the situation, explains why it is empty, and offers a next step: "You have no saved addresses yet. Add one now to speed up checkout." A poor empty state shows a blank area, or a cryptic "No data", leaving the person to wonder whether something broke. Empty states are an opportunity to teach: they can explain a feature at the moment the person encounters it, when the explanation is most relevant.
A no-results state, after a search or a filter, follows the same rule. It should say plainly that nothing matched, explain which search or filters were applied, and offer a way forward: clear the filters, try a broader term, or browse a related category. It should not blame the person, with phrases such as "You searched for the wrong thing", and it should not show an error style that suggests a system failure when the system worked correctly and simply found nothing. The distinction matters: a system error needs a fix, while a no-results state needs a new query, and confusing the two sends the person down the wrong path. Preserve the search query and the active filters in a no-results state, so the person can adjust them rather than retyping them.
Waiting states need writing as well. While a form submits, searches, or uploads, the person should see that work is happening, what is happening, and roughly how long it may take, where that can be honestly stated. "Sending your application…" is better than a spinning icon alone, because it names the action. "Uploading your file. This may take a minute on a slow connection" is better still, because it sets an expectation and reduces the urge to press again or navigate away. If waiting will take a long time, offer a way to continue later, or a confirmation that the work will complete even if the person leaves, where that is true. Never promise completion on leaving if the submission would actually be cancelled.
Test these states deliberately, because they are easy to overlook. View the form with no saved data, search for something that cannot match, throttle the connection and submit, and read what appears. If any state is blank, cryptic, or misleading, write it properly before release. The states around a form are where trust is built or lost, because they appear at moments of uncertainty — nothing yet, nothing found, still waiting — and a clear sentence at such a moment is worth more than a polished layout at a moment when everything is already going well.
Check: What should an empty state offer besides an explanation?
Section 45 — Confirmation dialogs for destructive form actions
Some form actions cannot be undone: deleting an account, discarding a long application, removing a saved payment method, or publishing something that cannot be unpublished. For those actions, a confirmation dialog is appropriate. It interrupts the person before the irreversible step, states clearly what will happen, and offers a way to cancel safely. A good confirmation names the specific thing that will be lost or changed, not just the category: "Delete the address '10 High Street'?" is clearer than "Delete this item?" It states the consequence: "This cannot be undone" where that is true, or "You can add it again later" where recovery is possible. And it offers two clearly labelled actions, such as "Delete address" and "Keep address", rather than a vague "OK" and "Cancel" that force the person to re-read the dialog to know which button does what.
Confirmation dialogs should be used sparingly. If every minor action requires confirmation, people learn to dismiss dialogs without reading them, and the dialog for a truly destructive action will be dismissed just as quickly. Reserve confirmations for actions that are destructive, irreversible, or costly, and make ordinary actions, such as saving a draft or moving to the next step, work without interruption. When a dialog is shown, it must trap focus, be reachable by keyboard, and be announced to screen readers, so that the person who most needs to understand the consequence can do so. The cancel action should be easy to find and should return focus to the element that opened the dialog, with no change made.
The wording of the confirmation's buttons matters as much as the message. A button labelled "Delete" beside a button labelled "Cancel" is ambiguous if the person reads only the buttons: cancel what, the dialog or the deletion? Labels that name the outcome, such as "Delete address" and "Keep address", remove that ambiguity. Avoid also the pattern where the destructive action is the most prominent button, styled as the primary action, because that invites a mistap. Make the safe action — keeping, cancelling, going back — easy to choose, and make the destructive action require a deliberate, second look. Some systems add a further guard for the most serious actions, such as typing a name or a word to confirm, but that guard should be reserved for rare, high-stakes deletions, not imposed on everyday tasks.
Test confirmations by trying to trigger them accidentally: tab quickly, press Enter, tap near the edge of a button on a phone. Check that an accidental trigger does not lead to an accidental deletion, and that a deliberate deletion is still possible without confusion. Check also that cancelling a dialog leaves the form exactly as it was, with all answers intact. A confirmation dialog is a safety net, and like any safety net, it should catch real falls without tripping people who are walking normally.
Check: Why should a confirmation button say "Delete address" rather than "OK"?
Section 46 — Login and signup forms without traps
Login and signup are the forms people meet most often, and they are also the forms where small traps cause the most frustration. A login form should ask for the identifier and the secret, label both clearly, and offer a visible path for a forgotten secret. A signup form should ask for the smallest set of information needed to create an account, explain why each field is needed, and not demand details that can be collected later, after the person has experienced the service. Both forms should work with password managers, with autofill, and with the browser's saved credentials, because fighting those tools makes login harder for exactly the people who are trying to be secure.
Password rules on signup need the care covered earlier: show the rules before typing, allow long passwords and spaces, do not impose arbitrary character requirements, and provide a show-hide control. Username rules need equal care: state what characters are allowed, whether a username must be unique, and how uniqueness will be checked, without revealing whether a chosen username is taken in a way that helps an attacker enumerate accounts, where that is a concern. Email verification, where it is used, should be explained before signup, so the person expects a message and checks the right inbox, and the verification step should not trap the person on a page with no way to resend the message or correct a mistyped address. A signup that collects an address, then offers no way to fix a typo in it, has built a dead end into its first step.
Error handling on login deserves special restraint. As noted earlier, a login error should not reveal whether the identifier or the secret was wrong, because that distinction helps an attacker test identifiers. A neutral message, such as "That combination does not match our records", plus a path to reset the secret and a path to recover the identifier, is safer and still helpful. Rate limiting and lockouts, which protect against guessing, should be explained honestly when they trigger: "Too many attempts. Try again in a few minutes" is better than a silent failure, and it should not lock a legitimate user out permanently for a few mistakes. Never show a password back in plain text in an error message, a log, or a confirmation, even to the person who typed it.
Test login and signup as a new person, as a returning person, and as a person who has forgotten their secret. Test with a password manager, with autofill, and on a phone. Test the recovery flow end to end, including the case where the recovery message goes to spam or the person mistyped their address. A login form that is quick for a returning user, clear for a new user, and recoverable for a forgetful user is doing its job. One that is quick only for the designer, who already knows the credentials, is not.
Check: Why should a login error not say whether the username or password was wrong?
Section 47 — Preserving input when something goes wrong
When a form fails, whether because of a validation error, a server error, or a lost connection, the person's answers must survive. That rule sounds obvious, yet it is broken constantly, often because a form is re-rendered from scratch after an error, or because a page reload clears fields that were never saved. The principle is simple: an error in one field must never destroy answers in other fields. A person who wrote a long message, chose options carefully, and then missed one required field should be able to fix that one field and resubmit, not rewrite the whole form. Preserving input is not a nicety; it is a condition of trust, because a form that destroys work teaches people not to invest effort in it.
Preservation has several layers. On the front end, validation errors should be shown without clearing any field, and the form should re-display with every value intact, including checkboxes, radio selections, dropdown choices, and textarea content. On submission failure, such as a network error, the form should remain filled, the submit button should become usable again, and the error should explain what happened and what to do next. On navigation, draft saving, covered earlier, provides a safety net for accidental back-button presses and tab closures. On the server side, a failed submission should return the submitted values to be re-rendered, not a blank form with a generic error at the top. Each layer catches a different kind of failure, and together they make the form resilient.
Special care is needed for sensitive and complex fields. Password fields are usually cleared on error for security, and that is acceptable, provided the person is told to re-enter them and no other field is cleared with them. File uploads are harder: a file chosen before an error may need to be re-chosen if the form reloads, which is frustrating, so the upload handling should preserve the file reference where possible, or at least explain clearly that the file must be chosen again and why. Dynamic fields, such as fields revealed by a choice, must also be preserved in their revealed state, not collapsed back to hidden, because a person who returns to find their conditional answers vanished will assume the form ignored them.
Test preservation systematically. Fill every field, trigger an error in the last field, and check that every earlier field survives. Trigger a network failure and check the same. Refresh after an error and check what survives, and document honestly where it does not, so the team can fix it rather than pretending it works. A form that preserves input through failure feels respectful, because it treats the person's effort as valuable. A form that does not feels careless, however beautiful its success path looks.
Check: What is the rule about answers in other fields when one field fails?
Section 48 — Forms, keyboards and screen readers together
A form that works with a mouse but not with a keyboard is unfinished, and a form that works visually but not with a screen reader is unfinished in a different way. Keyboard testing is straightforward: tab through the form in order, check that every control can be reached and operated, that the tab order follows the visual order, that no control traps focus, and that the submit button can be reached and activated. Check also that Shift and Tab moves backwards sensibly, that dropdowns and date pickers can be operated without a mouse, and that any custom control, such as a custom dropdown or a toggle, is reachable and operable by keyboard. If a control can only be operated by clicking, it excludes keyboard users entirely, and it should be replaced or fixed.
Screen reader testing adds the question of meaning. Does each field announce its label, its help text, its required state, and its error when relevant? Do groups announce their legends? Do radio groups announce how many options there are and which is selected? Does the error summary announce on submission failure, and does focus move to it? Does a dynamic change, such as revealing new fields, announce itself, or does it happen silently, leaving the screen reader user unaware that new questions appeared? These questions cannot be answered by looking at the form; they require testing with a screen reader, or at least a careful inspection of the markup: labels connected, groups structured, errors described, and live regions used only where a change genuinely needs announcing.
Custom controls are the most common source of keyboard and screen reader failures. A div styled to look like a checkbox, without the semantics of a checkbox, will not announce as a checkbox, will not be toggled by the space key, and will not be recognised as a form control. The safest approach is to use native controls wherever possible, and to style them, rather than rebuilding them from generic elements. When a custom control is unavoidable, it must replicate the native control's keyboard behaviour, focus visibility, and accessible name, role, and state, and it must be tested as thoroughly as a native control. That work is often more than the visual customisation was worth, which is why native controls are the default choice of experienced developers.
Test the whole form without a mouse, and if possible, with a screen reader, before release. Fill it, make mistakes, fix them, submit it, and confirm success, all without clicking. If any step requires sight or a mouse, fix it. Accessibility in forms is not a separate feature to add at the end; it is the form working as it should for everyone, and the keyboard and screen reader tests are simply ways of checking that the form's meaning, not just its appearance, is complete.
Check: Why is a div styled as a checkbox not a substitute for a real checkbox?
Section 49 — Reviewing a form before it goes live
Before a form goes live, review it as a whole, not just as a collection of fields that each passed a test. Start with the purpose: can a stranger tell, within a few seconds, what the form is for and what happens after submission? Read the labels, help text, button labels, error messages, and confirmation in order, aloud, and check that they tell one coherent story, in plain language, without jargon, contradictions, or missing steps. Check that every field is necessary, that every required field is genuinely required, and that every optional field is marked. Remove any field that cannot justify itself, because a field that survives review without a reason will cost every future user time and attention.
Next, review the mechanics. Check that every control has a name, a label, and an appropriate type, autocomplete token, and input mode. Check that validation on the front end matches validation on the server, that error messages are specific and accessible, that focus moves sensibly after errors and success, that drafts and input are preserved through failure, and that double submission is prevented. Check the form on a phone, with a keyboard, with large text, and with a screen reader if possible. Check the success path, the failure paths, and the edge cases: empty submissions, long answers, special characters, back-button presses, and refreshes. A review that only checks the success path is not a review; it is a demonstration.
Also review the surrounding promises. Does the form explain why personal data is needed, how it will be used, and how long it will be kept, where that matters? Are consent checkboxes separate, unchecked by default, and honest? Is the privacy notice reachable from the form without losing the form's data? Are there any misleading defaults, any pre-checked marketing boxes, or any button labels that promise more than the button does? These are not styling details; they are the form's honesty, and they are easiest to fix before launch, when changing a label costs minutes, rather than after launch, when changing it requires explaining why it was wrong.
Finally, record the review. Note what was checked, what was fixed, and what remains known but unresolved, with a reason. That record helps the next person who edits the form, and it prevents the same mistakes from returning in a redesign. A form that has been reviewed for purpose, mechanics, and honesty, and tested with real people and real content, is ready to go live. One that has only been looked at in a design file is not, however polished it appears, because the form's real test begins when a stranger, on a phone, in a hurry, tries to complete it. A useful review habit is to compare the form with its earlier version and ask what changed for the user, not just for the code: a renamed label, a reordered field, or a new required mark can confuse returning users even when the change looks minor internally. Note those user-facing changes explicitly, so support and documentation can answer questions about them honestly.
Check: What three areas should a pre-launch form review cover?
Section 50 — A form is a promise
Every form makes a promise, whether it states it or not. It promises that the questions are necessary, that the answers will be handled with care, that errors will be explained kindly, and that submission will lead to the outcome described. Keeping that promise is the whole craft of form design. The techniques in this chapter — clear labels, honest validation, specific errors, accessible markup, careful timing, preserved input, and plain language — are not separate tricks. They are all ways of keeping the same promise from different angles. A form that keeps it earns completion, accuracy, and trust. A form that breaks it, by losing data, hiding errors, demanding unnecessary information, or misleading about consent, loses all three at once.
Think about the last form you abandoned, and why. It was probably not because the form was ugly. It was because a field was unclear, an error was cryptic, a password rule appeared too late, a long answer vanished, or a submit button promised one thing and did another. Those are the failures this chapter has tried to prevent, and they share a root cause: the form was designed from the system's point of view, not the person's. Reversing that perspective — starting from the person's goal, their device, their interruptions, and their doubts — is the single most useful habit a front-end developer can build for forms. It costs little, it requires no new library, and it improves every form you touch.
Forms will keep evolving. New input types, new browser features, and new patterns for authentication and payment will appear, and some of the specific attributes in this chapter will age. The principles will not: ask only for what you need, explain why, make the format clear before typing, give feedback that helps rather than scolds, preserve effort, respect the device, and be honest about consent and consequences. If you hold to those principles, you can learn each new technique as it arrives and judge it by whether it serves the person filling the form, not by whether it looks modern in a demo.
Before you move on, return to a form you have built or used, and review it against this chapter. Can you name every field's purpose? Can you complete it with a keyboard, on a phone, after an error, without losing work? Do its error messages tell a stranger how to fix the problem? Does its success message say what happens next? If any answer is no, you have found your next improvement, and it will matter more to real users than any visual redesign. That is the promise to keep, and the work of this chapter is learning to keep it, one field at a time.
Check: In one sentence, what promise does every form make to the person filling it?
Practical task
Build a signup form for a fictional learning site with: a visible label for every field, one required and one clearly marked optional field, an email field with a helpful suggestion note (not an auto-correction), a password field with a show-hide button, an error summary plus inline errors that appear on submit and clear when fixed, focus moved to the summary on failure, a success confirmation that states what happens next, and preserved input when an error occurs. Test it with a keyboard alone, on a phone-sized screen, and by submitting it empty, then fix every failure you find before calling it done.
Chapter questions
- A signup form rejects a valid email address because its pattern is too strict. What is wrong, and how would you fix it without weakening real validation?
- A long application form loses all answers when one field fails. Explain the preservation failures involved and how you would fix each layer.
- Design the error handling for a checkout form: where should errors appear, what should they say, and where should focus go after a failed submission?
- A client wants a reset button next to submit and pre-checked marketing consent. Explain, in plain words, why both requests should be refused or redesigned.
- Rewrite a vague error message ("Invalid input") for a postcode field into a specific, accessible, fixable message, and explain each choice you made.