The <form> element
This is where the conversation with your user begins. Every time someone
signs up, logs in, or messages you through a contact form, their data travels
through a <form>. It's the channel your app uses to receive information from
the outside world.
All controls (text boxes, checkboxes, buttons) are grouped inside it:
<form>
<!-- controls go here -->
</form>
The most basic control: <input>
<input> is a self-closing tag that, depending on its type attribute,
becomes different controls (a text box, a checkbox, etc.). It's the chameleon of
the form.
The name attribute is the key the data travels under. ⚠️ CLASSIC TRAP: if
you forget name, the field shows up, the user fills it in... and nothing gets
sent. Like talking with no one listening.
<input type="text" name="city" />
The <label> + <input> pair: key to accessibility
A field without a label is a test with no question: the user doesn't know what to
type and a screen reader doesn't know how to announce the control. The
solution is <label>.
The most robust way to join them is by reference: the for attribute of the
<label> points to the id of the <input>. ⚠️ CLASSIC TRAP: they must
match exactly (a for="email" needs an id="email", not id="mail"):
<label for="email">Email address</label>
<input type="email" id="email" name="email" />
This brings three concrete benefits:
- Accessibility: screen readers read "Email address" when focusing the field.
- Usability: when you click the
<label>text, focus jumps to the control (very handy for checkboxes and radios, which are small). - Semantic clarity: it is explicit which label describes which control.
Golden rule: every form control should have an associated
<label>. If you usefor/id, make sure the values are identical and unique on the page.
There is also the wrapping variant (<label>text <input /></label>),
but for/id is more explicit and validates more reliably. Get comfortable with
this pair: you'll see it in every form on the planet.