Start with a name users can find
This guide assumes a standard HTML form in a modern browser, with no framework or custom input library. Imagine a simple account form with fields for an email address and a password. Before adding validation or styling, give each field a short, visible label: “Email address” and “Password.” A person scanning the page can then see what each field asks for, while someone using a screen reader can hear the field’s name when they reach it.
For a typical text input, connect its label using the label’s for attribute and the input’s id. Those values must match, and each id must be unique on the page. Placing a label visually near an input is not enough if the relationship is missing in the document. Try clicking the label: in a correctly connected example, the associated input receives focus. Keep labels visible even after users enter a value; placeholder text disappears as they type and should not be the only way to identify a field.
Name the information you need rather than describing the control itself. “Email address” is more useful than “Text box,” and “Create a password” is clearer than “Enter here.” If a field is optional, say so in its label when that distinction matters. If most fields are required, a brief form-level explanation can establish that convention, but the requirement should still be available to assistive technology through native form semantics.
Put instructions where they answer a question
A label identifies a field; an instruction explains how to complete it. For the password field, an instruction might say, “Use at least 12 characters.” Keep it beside the field and present before submission, rather than revealing it only after a failed attempt. If a field needs a particular format, show an example in the instruction without making users guess from a placeholder.
When an instruction is important to completing an input, connect it with aria-describedby. Give the instruction element a unique id, then set the input’s aria-describedby value to that id. In this example, a screen reader can announce the password label and its guidance when the input receives focus. The instruction remains visible for everyone else. Avoid repeating the entire label in the instruction; each piece of text should add something useful.
Use the browser’s input types where they fit the information requested, such as email for an email address. They can provide helpful behavior, including an appropriate on-screen keyboard on some devices, but they do not replace a clear label or explanation. Do not impose a rigid format unless it serves a real need.
Give related choices shared context
Some questions contain several controls but need one shared prompt. Suppose the form asks, “How would you like us to contact you?” with radio choices for email and phone. Each choice needs its own label, but the group also needs a name. Use a fieldset to contain the related controls and a legend for the question. This lets users understand what the choices refer to as they move through the group.
The same pattern works for a set of related checkboxes. Make the legend specific enough to explain the task, and put any rule such as “Choose all that apply” with the group. Do not rely on spacing or a visual heading alone to convey the relationship. Before building a custom selection component, consider whether native radio buttons, checkboxes, or a select control already express the choice clearly.
Make validation feedback actionable
An error should tell users what happened and how to fix it. “Enter an email address” helps when the field is empty; “Enter an email address in the form name@example.com” is more useful when the value does not match the expected format. Place the message near its field and connect it through aria-describedby, alongside any existing instruction. If the input is invalid after validation, aria-invalid set to true can communicate that state to assistive technology.
Do not identify errors by color alone. Use text, and preserve the field’s label so users know which value to change. After an attempted submission, a short error summary can help people locate multiple problems; links to the affected fields can make that summary easier to use. If the form prevents submission, move focus deliberately to the summary or first invalid field, then test that the next step is clear. Avoid announcing errors on every keystroke, which can interrupt someone who is still typing.
Check the experience, not just the markup
Test the account form with only a keyboard. Can you reach each field in a sensible order, see where focus is, and submit or correct the form without a mouse? Then inspect it at a narrow viewport or with enlarged text: labels, instructions, and errors should remain close enough to their fields to make sense. These checks often reveal problems that are easy to miss when viewing the form at its default size.
Finally, listen to the form with a screen reader if one is available. Check that each field announces an understandable name, that essential instructions are available at the right moment, and that validation does not obscure what to do next. A good result is straightforward: users can identify every input, understand what it expects, and recover from a mistake without having to infer meaning from layout or color.



