HTML Forms
Learn to build forms people can actually use: labels tied to controls, the right input types, radio groups under fieldsets, and the validation attributes that do real work.
Basic
Forms are where the web stops being a magazine and starts being software, and they are also where most websites quietly fail people. Every label you forget to connect, every control replaced by a styled div, every instruction written only in placeholder text lands directly on the reader trying to give you their address or their money.
Quick check
Complete the HTML with the element that groups controls into a sub-group with an accessible caption.
<form>
<><legend>Contact</legend>
<input name="email">
</fieldset>
</form>
The good news is that usable forms are mostly a matter of letting the built-in elements do their jobs. This lesson covers the structural half of that: labels, controls, and grouping. What happens when the form is submitted belongs to the JavaScript curriculum.
The specification, translated
The HTML Standard uses a few precise categories that are easy to blur together. A control can be
form-associated (it can have a form owner),
listed (it appears in
form.elements),
submittable (it can contribute a name/value pair when the form is submitted), and/or
resettable (it participates when the form is reset). These are specification categories, not four different kinds of form you need to memorize. The useful author rule is: use the native control for the job, give it a label, give it a meaningful
name when its value should be submitted, and let the browser handle its native form behavior.
The label is not optional
Every control needs a label, connected to it by matching the label's
for attribute to the control's
id. That connection is not decoration: it gives screen readers the control's name, gives voice-input users a word to say, and makes the whole label clickable for everyone with an imprecise pointer, which on a small touchscreen is everyone.
|
|
A label and its control, joined by matching for and id.
A control without a connected label has an accessible name of nothing, and screen readers announce it with just its type: a lonely edit text in a field of them. If you take one habit from this lesson, make it checking that pairing every time you write a control.
Input types earn their keep
The
<input> element's
type attribute changes both behavior and keyboard. An
type="email" gets a keyboard with an at sign on phones and basic format checking for free.
type="number" invites stepper buttons and rejects letters.
type="date" opens a real calendar instead of making everyone guess your preferred date format. The browser does all of it, no script required.
Type | What the reader gets | Use it for |
|---|---|---|
text | A plain single-line field | Anything without a better type |
At sign on mobile keyboards, format checking | Email addresses | |
password | Masked entry, offered to password managers | Passwords |
number | Steppers, numeric keyboard on phones | Quantities that are truly numeric |
date | A real calendar picker, consistent format | Any calendar date |
checkbox | A toggle the reader can operate with one key | Yes or no, terms, options |
radio | A group where exactly one is on | Small exclusive choices |
Resist
type="number" for values that merely look numeric, like card numbers or postcodes. Steppers make no sense there, leading zeros vanish, and paste is a fight. A
type="text" with
inputmode="numeric" gives phones the right keyboard without the rest of the baggage.
Radio groups and the fieldset
Radio buttons only make sense as a group: same
name, different
value, exactly one selected. Group them inside a
<fieldset> with a
<legend>, and the whole question gets a name. Screen readers announce the legend with each radio, so a reader tabbing into the middle of the group still knows which question they are answering.
|
|
One question, three answers, one shared name.
Checkboxes answer a different question. Each one is independent and each needs its own honest label, including the ones that look like a group on screen. A row of toggles without a fieldset is fine; a row of radios without one is a trap for anyone who arrives mid-group.
Textareas, selects, and buttons
The
<textarea> holds multi-line text and should always be given
rows so its height is honest before any CSS loads. The
<select> is a closed list of
<option>s; it is the right control when the answers are known and few, and a wrong one when it hides a country list behind two clicks. Its first option should be a real choice or an explicit empty one, never a selected placeholder that pretends to be an answer.
Buttons come from
<button>, which submits the form by default, resets it with
type="reset", or does neither with
type="button". The element takes real text, icons, and focus styling for free, which is why a div with an onclick handler is never an acceptable button no matter how it looks.
Validation the browser will do for you
A handful of attributes turn the browser into a first line of defense.
required blocks empty submission.
min,
max, and
pattern describe what valid means.
autocomplete lets password managers and autofill do their work, which measurably reduces both typos and abandonment. The messages browsers produce are generic, so treat these attributes as a safety net under your own clearer guidance, not as your only explanation of the rules.
|
|
Required, bounded, and explained in text that never disappears.
Quick check
A radio group has three inputs with the same name. Only the first radio has required. What does the browser require before the form can be submitted?
A form worth filling
The example below is a bakery preorder form using every idea from this lesson. In the preview you can focus fields with labels and Tab, open the date picker, and toggle the radios. Try clicking the word above a field instead of the field itself: the label being clickable is the pairing working. Submission is deliberately left unwired, so the form can be explored safely inside the preview.
Output
Ready to run.
Mistakes worth avoiding
Placeholder-as-label. The name of the field should survive the first keystroke.
Radios without a fieldset and legend. The question disappears for anyone who arrives mid-group, which keyboard users always do.
A select for a yes-or-no question. Two radios are faster to operate than any dropdown.
Disabling the submit button until the form is perfect. Disabled buttons eat error messages and keyboard focus, and the reader is left guessing which field is still wrong.
Styling focus outlines away. The outline is the keyboard reader's cursor; move or restyle it, never remove it.
Quick check
If you can wire a label to a control without looking it up, explain why radios want a fieldset while checkboxes do not, and name two things an input type gets you for free, you have this lesson. When you are ready, take the HTML Forms quiz.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.