Forms and Inputs
Forms are the web's primary mechanism for collecting user input — built from semantic elements that tell the browser (and assistive tech) exactly what each field is.
- Build a basic HTML form with the correct semantic structure
- Pair every input with a <label> using the for/id relationship
- Choose appropriate type attribute values for different kinds of input
- Understand what action and method on <form> do (without needing a server yet)
Almost everything interactive on the web that collects information from a user goes through an HTML form: search boxes, login screens, checkout flows, comment sections. Before JavaScript frameworks and custom inputs, the form was the only mechanism. Understanding it from the HTML level means you understand all of those patterns at their foundation.
The form element
<form> wraps a set of controls and defines what happens when they are
submitted. Two attributes control the submission:
action— the URL the browser sends the data to. If omitted, the form submits to the current page's URL.method— how the data is sent.GETappends data to the URL as a query string;POSTsends it in the request body (invisible in the URL and suitable for sensitive data).
<form action="/search" method="GET">
<input type="text" name="query">
<button type="submit">Search</button>
</form>Submitting this form with "sourdough" in the box navigates to
/search?query=sourdough. That is why search forms use GET — the URL is
shareable and bookmarkable.
A login form, by contrast, should use POST so the password is not exposed in
the URL or browser history:
<form action="/login" method="POST">
…
</form>You do not need a server to experiment with forms. Omit the action attribute
and the form submits to itself — you will see the query string appear in the
address bar. That is enough to understand GET behaviour while learning.
Labels and inputs
Every user-facing control needs a label. The
<label> element names a field and links to its input via matching for and
id values:
<label for="email">Email address</label>
<input type="email" id="email" name="email">When the for attribute on <label> matches the id on the <input>:
- Clicking the label focuses the input — a larger click target, especially useful on mobile.
- Screen readers announce the label text when the user moves to the input.
- Browsers can show better mobile keyboards (e.g. the email keyboard for
type="email").
Never use placeholder as a substitute for a label. Placeholder text disappears
as soon as the user starts typing, leaving them with no reminder of what the
field was for.
Input types
The type attribute on <input> does most of the heavy lifting. The browser
validates, formats, and picks the right keyboard automatically:
<!-- Free text -->
<input type="text" id="name" name="name">
<!-- Email — validates format, shows @ keyboard on mobile -->
<input type="email" id="email" name="email">
<!-- Password — masks characters -->
<input type="password" id="password" name="password">
<!-- Number — numeric keyboard, min/max/step validation -->
<input type="number" id="age" name="age" min="0" max="120">
<!-- Checkbox — checked or unchecked -->
<input type="checkbox" id="subscribe" name="subscribe">
<!-- Radio — one of a group (all share the same name) -->
<input type="radio" id="size-s" name="size" value="S">
<input type="radio" id="size-m" name="size" value="M">
<input type="radio" id="size-l" name="size" value="L">
<!-- Submit button — clicking it submits the form -->
<input type="submit" value="Send">Radio buttons need a label for each option and should be wrapped in a
<fieldset> with a <legend> to give the group a name:
<fieldset>
<legend>T-shirt size</legend>
<label for="size-s">Small</label>
<input type="radio" id="size-s" name="size" value="S">
<label for="size-m">Medium</label>
<input type="radio" id="size-m" name="size" value="M">
<label for="size-l">Large</label>
<input type="radio" id="size-l" name="size" value="L">
</fieldset><fieldset> groups related controls; <legend> is the label for the group.
Screen readers announce the legend before each control inside the fieldset.
Multi-line text and dropdowns
Two more controls that appear in nearly every form:
<textarea> — multi-line text input. Unlike <input>, it has a closing tag
and can contain a default value as content:
<label for="message">Message</label>
<textarea id="message" name="message" rows="5" cols="40">
Default text here if needed.
</textarea><select> and <option> — a dropdown menu:
<label for="country">Country</label>
<select id="country" name="country">
<option value="">-- Please select --</option>
<option value="us">United States</option>
<option value="gb">United Kingdom</option>
<option value="ca">Canada</option>
</select>The value on each <option> is what gets sent with the form; the text inside
is what the user sees. An empty value on the placeholder option ensures the
user is forced to make a real selection if the field is required.
Button types
<button> is more flexible than <input type="submit">:
<!-- Submits the form -->
<button type="submit">Sign up</button>
<!-- Does nothing on its own — useful for JS-driven actions -->
<button type="button">Preview</button>
<!-- Clears all fields back to their defaults -->
<button type="reset">Clear form</button>Always set type on a <button> inside a form. The default is type="submit",
which means a "Preview" button with no type attribute will accidentally submit
the form.
Required fields
The required attribute prevents form submission if the field is empty:
<label for="email">Email address <span aria-hidden="true">*</span></label>
<input type="email" id="email" name="email" required>The asterisk is a visual convention for "required." Marking it aria-hidden="true"
tells screen readers to ignore it — the required attribute on the input already
communicates that the field is mandatory through assistive technology.
A complete example
<form action="/signup" method="POST">
<div>
<label for="fullname">Full name</label>
<input type="text" id="fullname" name="fullname" required>
</div>
<div>
<label for="email">Email address</label>
<input type="email" id="email" name="email" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<div>
<label for="bio">Short bio (optional)</label>
<textarea id="bio" name="bio" rows="3"></textarea>
</div>
<div>
<input type="checkbox" id="terms" name="terms" required>
<label for="terms">I agree to the terms of service</label>
</div>
<button type="submit">Create account</button>
</form>Where to go next
You have the full vocabulary of the HTML document — structure, semantics, attributes, links, images, and forms. The Lab: Build a Well-Structured Page puts all of it together into a realistic exercise where you mark up a complete page from a content brief.
Attributes, Links, and Images
Attributes give elements extra information — and two elements that depend entirely on attributes are the anchor and the image.
Lab: Build a Well-Structured Page
Apply semantic HTML to mark up a news article page from a plain-text brief — getting the structure right before any CSS is applied.