Forms fundamentals: form, input types, and labels
Forms are how a page collects real input — the difference between a brochure and something a visitor can actually act on. This part builds a genuinely simple real form (a newsletter signup) to establish the fundamentals correctly before part 11's more complex checkout form.
The real newsletter signup form
<form action="/subscribe" method="post">
<label for="email">Email address</label>
<input type="email" id="email" name="email" required />
<button type="submit">Subscribe</button>
</form><form>: action and method
action is the URL the form's data is sent to when submitted; method is how it's sent — "post" for data that changes something server-side (creating a real subscriber, like this form does), "get" for data that only retrieves something (a search form, where the query showing up in the URL is actually useful for sharing or bookmarking the search).
Input types: real, purpose-built keyboards and validation
<input type="email" name="email" />
<input type="tel" name="phone" />
<input type="number" name="quantity" min="1" max="10" />
<input type="date" name="delivery-date" />
<input type="text" name="name" />Each type value isn't cosmetic — type="email" triggers real, built-in format validation (covered fully in part 11) and, on a phone, switches the on-screen keyboard to one with @ and .com easily accessible; type="tel" brings up a numeric phone keypad; type="number" brings up a numeric keypad and adds increment/decrement controls. Using type="text" for all of these works, but it throws away real, free browser behavior a more specific type provides at no extra cost.
The label association: the single highest-impact accessibility fix
<!-- correct: for/id association -->
<label for="email">Email address</label>
<input type="email" id="email" name="email" />
<!-- also correct: wrapping instead of for/id -->
<label>
Email address
<input type="email" name="email" />
</label>
<!-- broken: visually looks identical, but isn't actually associated -->
<span>Email address</span>
<input type="email" name="email" />A <label> connected to its input — either by matching for/id attributes, or by wrapping the input directly — does two genuinely important things: clicking the label text focuses the input (useful for anyone with limited motor precision, since it enlarges the real clickable target), and a screen reader announces the label text when the input receives focus. The broken version above can look pixel-identical to a sighted user while being completely unusable information for a screen reader user, who hears only "edit text, blank" with no indication of what to type.
This one pattern — real <label for>/id association — is arguably the single highest-impact, lowest-effort accessibility fix in all of HTML. It costs nothing visually, takes seconds to add, and is the difference between a form a screen reader user can actually complete and one they can't use at all.
Placeholder text is not a label
<!-- wrong: placeholder as the only label -->
<input type="email" name="email" placeholder="Email address" />Placeholder text disappears the moment a visitor starts typing, isn't reliably announced by every screen reader the way a real <label> is, and fails a genuinely common real scenario — someone who gets interrupted mid-form and returns to it has no visible reminder of what a field was for, since the placeholder vanished with their first keystroke. Placeholder text is fine as a supplementary hint (an example format), never as a field's only identifying label.
The submit button
<button type="submit">Subscribe</button><button type="submit"> (or <input type="submit">) is what actually submits the form — a plain <button> with no type attribute defaults to type="submit" inside a form too, which is a real, easy-to-miss source of bugs if a form has multiple buttons and one was meant to do something else entirely, like toggling a password's visibility.
Next: forms deep dive — real validation attributes, fieldsets, and building the actual checkout form with genuinely accessible structure.