So far, everything you’ve built has run one way: you put content on the page, and the visitor reads it. Forms flip that around. A form is how a website takes information in — a login box, a search bar, a sign-up sheet, a contact message. Any time a site asks you to type something and submit it, a form is doing the work.
This is where HTML starts to feel interactive. We won’t cover what happens to the data after it’s submitted — that’s a backend topic for much later. For now, we’ll focus on building the form itself: the fields, the labels, the buttons, and how to wire them together correctly.
The <form> element
Everything starts with the <form> element, which wraps all the fields that belong together:
<form action="/submit" method="post">
<!-- input fields go here -->
</form>
Two attributes set up where the data goes and how:
actionis the URL the form data is sent to when submitted.methodis how it’s sent — usuallypost(for data that changes something, like a sign-up) orget(for things like a search, where the data ends up in the URL).
Don’t sweat these two just yet — they only start to matter once you have a backend ready to receive the data. The key idea for now is that <form> is the container that groups your fields together and gives you a “submit” action.
The <input> element
The <input> element is the workhorse of forms. It’s a single, self-closing tag that turns into a completely different kind of field depending on its type attribute:
<input type="text" />
<input type="email" />
<input type="password" />
<input type="checkbox" />
That one element, with different type values, covers a huge range of fields. Here are the ones you’ll reach for most often:
type |
What it gives you |
|---|---|
text |
A single-line text box |
email |
A text box that expects an email (mobile keyboards adapt) |
password |
A text box that hides what you type |
number |
A field for numbers, often with up/down arrows |
checkbox |
A box you can tick on or off |
radio |
A round button for picking one option from a group |
date |
A date picker |
file |
A file upload button |
submit |
A button that submits the form |
The same tag, a different type, a completely different field. That’s what makes <input> so central.
Use the right input type — it helps users
Picking the correct type does more than you’d think. On a phone, type="email" brings up a keyboard with the @ symbol ready, and type="number" brings up a number pad. type="date" gives users a real calendar to tap instead of typing. The right type makes your form easier and faster to fill in, especially on mobile — so choose deliberately, don’t just use text for everything.
Labels: the part beginners skip
Here’s something crucial that beginners love to skip: every input should have a label. A label is the text that tells the user what a field is for — and in HTML, it’s a real element, <label>, not just some words sitting next to the box.
The right way to connect a label to its input is with the for attribute, which matches the input’s id:
<label for="email">Your email address</label>
<input type="email" id="email" />
The for="email" on the label points to the id="email" on the input. That single link does two important things:
- Clicking the label focuses the input (try it — it makes checkboxes and radio buttons much easier to tap).
- Screen readers announce the label when the user reaches the field, so they know what to type.
A form without labels is a broken form
It’s tempting to skip labels and just put some text before each field, or rely on the placeholder (the grey hint text inside a box). Don’t. Placeholder text disappears the moment someone starts typing, and it’s not reliably read by screen readers. Without proper <label> elements, people using assistive technology can’t tell what your fields are for. Always pair every input with a real, connected label.
Text areas, dropdowns, and more
A few more field elements round out the basics. For longer, multi-line text — a message or a comment — reach for <textarea> instead of a single-line input:
<label for="message">Your message</label>
<textarea id="message" rows="5"></textarea>
For a dropdown menu where the user picks one option from a list, use <select> with <option> elements inside it:
<label for="country">Country</label>
<select id="country">
<option value="id">Indonesia</option>
<option value="my">Malaysia</option>
<option value="sg">Singapore</option>
</select>
And for a group of checkboxes or radio buttons, each gets its own input and label:
<input type="checkbox" id="terms" />
<label for="terms">I agree to the terms</label>
Notice that with a checkbox, it usually reads more naturally to put the label after the box — but the for/id connection works exactly the same either way.
Buttons
Finally, a form needs a way to submit. The simplest is a submit button:
<button type="submit">Send</button>
When clicked, it submits the form to wherever the action points. You could also use <input type="submit" value="Send" />, which does the same job, but <button> is more flexible — you can put icons or styled text inside it.
There are a few button types worth knowing:
type="submit"— submits the form (the default inside a form).type="reset"— clears all the fields back to empty.type="button"— does nothing on its own; used when you’ll wire it up with JavaScript later.
Putting a full form together
Let’s assemble everything into a small but complete contact form:
<form action="/contact" method="post">
<label for="name">Name</label>
<input type="text" id="name" />
<label for="email">Email</label>
<input type="email" id="email" />
<label for="message">Message</label>
<textarea id="message" rows="5"></textarea>
<label for="subscribe">
<input type="checkbox" id="subscribe" />
Subscribe to our newsletter
</label>
<button type="submit">Send message</button>
</form>
That’s a real, working form. Every field has a connected label, each input type matches what the field expects, and there’s a clear submit button. When a visitor fills it in and clicks “Send message,” the browser bundles up the data and sends it off to /contact. What happens next — saving it, emailing it, validating it on the server — is the backend’s job, which you’ll get to down the road.
HTML handles the form; the backend handles the data
HTML’s job ends at collecting the input and submitting it. Actually receiving that data, storing it, and responding is handled by server-side code — a separate skill you’ll pick up later. HTML can do some basic checks on its own, though, like marking a field required so the form won’t submit while it’s empty, or using type="email" so the browser checks for a valid email format. These built-in checks are a helpful first line, but real validation always happens on the server too.
Wrapping up
You can now build interactive forms — a big step up from static content:
<form>wraps the fields and defines where (action) and how (method) the data is sent.<input>is one tag that becomes many kinds of field via itstype— text, email, password, checkbox, radio, date, file, and more. Choosing the right type makes forms easier to fill in.<label>elements, connected to inputs withfor/id, are essential — for usability and accessibility alike. Never skip them.<textarea>handles multi-line text and<select>/<option>make dropdowns.<button type="submit">sends the form off.
With forms, you’ve now touched every major category of HTML content: text, links, images, and input. Next, we’ll tackle one more structural tool — the table — for laying out data in rows and columns.