<form>
tag control where data goes and how it travels there?action
sets the URL that receives the submitted data.
method
controls how it is sent:
get
appends data to the URL (fine for searches, never for passwords),
post
sends it hidden in the request body — the right choice for any sensitive or large data.
<form>
element — that wraps one or more controls: text fields, dropdowns, checkboxes, radio buttons, and buttons. When the user submits, the browser collects every control that has a
name
attribute and sends the data as key-value pairs. No
name
attribute, no data — the field is silently ignored with no error shown.<label>
element is not optional decoration — it is functional. A label linked to an input via matching
for
and
id
values does three things at once: it describes the field in plain language, it enlarges the click/tap target so users can click the label text to activate the field, and it tells screen readers exactly what each input is for. Remove the label and all three benefits disappear.type="email"
instead of
type="text",
and adding
required,
you get automatic format checking and submission blocking — no JavaScript needed. The browser enforces the rules and shows error messages in the user's own language.<form action="/send-message" method="post"> — The
action
is the destination URL where the browser delivers the data on submit. The
method="post"
keeps all data inside the request body, invisible in the URL bar. If you used
method="get"
here, the user's name, email, and message would appear in the address bar, in browser history, and in every server access log — a privacy failure on the very first page.
<label for="fullname">
and
<input id="fullname">
are linked because their
for
and
id
values are identical. This link is invisible in the browser but critical in behaviour: clicking the label text moves focus into the field, and a screen reader announces the label text when the input is focused. Without this link, a screen reader user hears only "edit text, required" — no clue what to type.
type="email"
and
required — Together these handle two layers of validation with zero JavaScript. The browser blocks submission when the field is empty (
required)
and when the value does not contain @ and a domain name (
type="email").
On mobile,
type="email"
also triggers the @ keyboard — a UX improvement that costs nothing.
<select>
and
<option> — Each
<option>
has a
value
(what the server receives) and display text (what the user sees) — these do not have to match. The first option here has
value=""
and acts as an empty prompt. Adding
required
to the
<select>
means the browser will block submission when that blank prompt is still selected.
<textarea>
vs
<input> — Unlike the self-closing
<input>,
a
<textarea>
has both opening and closing tags. Never put any text — not even a space — between them unless you want that text pre-filled in the box. The
rows
attribute sets visible height. The
name
attribute is required — without it the user's message is never submitted.
required
catch common errors before data reaches the server — wrong email format, empty required fields, numbers out of range — instant feedback in the user's language, no JavaScript written.type
triggers the right keyboard on phones:
type="tel"
shows a number pad,
type="email"
shows the @ key,
type="url"
shows .com. One attribute, better experience for every mobile visitor.<label>.
Without it, screen reader users hear "edit text" with no hint of what to type. A linked label also doubles the click/tap target — essential for users with motor difficulties.method="post"
keeps sensitive data out of URLs, browser history, and server logs. It is not complete security on its own — server-side validation is always required too — but it is the non-negotiable starting point for any form handling private data.for
/
id
pairs and
type="text"
where
type="email"
or
type="password"
should be. Be cautious if it suggests adding
aria-label
to inputs that already have a proper
<label>
— the HTML label is the preferred and simpler solution.
contact.html
with a full HTML skeleton. Inside
<main>,
add
<form action="#" method="post">.
Build a text input for Full name and an email input. Link each to its
<label>
using matching
for
and
id
values. Mark both
required.<select>
labelled "Subject" with at least three
<option>
choices, including a blank first option as a prompt. Add
required
to the select element itself.<textarea>
labelled "Your message" with
rows="6"
and
required.
Make sure nothing — not even whitespace — sits between the opening and closing textarea tags.<label>,
then a
<button type="submit">Send message</button>.
Try submitting with the email field empty — confirm the browser blocks it.id
and
name
attributes.name
attribute. A field without
name
is silently excluded from submitted data — the server never receives it and shows no error. Every control that collects data must have a
name.type="text"
for email and password fields. The browser skips format validation, shows the wrong mobile keyboard, and displays the password in plain text. Use the specific type that matches the data being collected.for
and
id
— for example,
for="email"
on the label but
id="user-email"
on the input. They must be identical and case-sensitive. The link fails silently — no warning, no error — and the label becomes useless decoration.method="get"
for login or contact forms. The submitted data — including passwords — becomes visible in the URL, browser history, bookmarks, and every server access log. Always use
method="post"
for any form that handles private data.<div>
to look like a submit button. It is not keyboard-focusable by default, not announced as a button by screen readers, does not respond to Enter, and does not submit the form. Use
<button type="submit">
— correct behaviour with no extra code.for
and
id,
apply the correct
type
and
required
for built-in validation, and explain why
method="post"
is required for sensitive data.
Welcome back to Jit4All