Forms & Inputs
Learn how to build interactive HTML forms that collect user data using inputs, labels, and buttons.
Almost every website you use has a form: a login screen, a search bar, a checkout page, a comment box. Forms are how the web talks back to you — they let users send information, not just receive it. In this lesson you will go from zero to building real, usable forms in plain HTML. No JavaScript required yet; HTML alone handles quite a lot.
#The <form> Element: Your Data Container
Every form starts with the <form> element. Think of it as a mailing envelope: you put all your form fields inside it, and when the user clicks Submit, the envelope gets sealed and sent somewhere. The two most important attributes on <form> are action (where to send the data) and method (how to send it).
<form action="/signup" method="post">
<!-- inputs go here -->
<button type="submit">Sign Up</button>
</form>Form = Envelope, Inputs = Pages Inside
Imagine filling out a paper form at the doctor's office. Each blank line you write on is an <input>. The whole stack of pages goes into an envelope (<form>), which you hand to the receptionist (action). The method GET is like writing your answers on the outside of the envelope (visible in the URL); POST tucks everything safely inside.
#Labels: The Unsung Heroes
A <label> tells users what an input is for. Always pair every input with a label — not just for looks, but because screen readers read the label aloud to blind users, and clicking the label focuses its input (a nice usability bonus). Connect them with matching for and id attributes.
<label for="username">Username</label>
<input type="text" id="username" name="username" placeholder="e.g. coolcoder42">id vs name — they do different jobs
id links the label to the input in the browser. name is the key that gets sent with the form data (like username=coolcoder42). You almost always want both, and they are often set to the same value — but they serve completely different purposes.
#Common Input Types
The type attribute on <input> is remarkably powerful. The browser changes its keyboard, validation, and appearance automatically based on this one attribute. Here are the types you will reach for most often:
<!-- Plain text -->
<input type="text" name="city" placeholder="Your city">
<!-- Email — browser validates the @ sign -->
<input type="email" name="email" placeholder="you@example.com">
<!-- Password — characters are hidden -->
<input type="password" name="password" placeholder="Min 8 characters">
<!-- Number — shows a spinner on desktop -->
<input type="number" name="age" min="1" max="120">
<!-- Checkbox -->
<input type="checkbox" id="terms" name="terms">
<label for="terms">I agree to the terms</label>
<!-- Radio buttons (one choice from a group) -->
<input type="radio" id="catPerson" name="pet" value="cat">
<label for="catPerson">Cat person</label>
<input type="radio" id="dogPerson" name="pet" value="dog">
<label for="dogPerson">Dog person</label>Radio buttons need the same name
Radio buttons become a group by sharing the same name value. The browser enforces that only one can be selected at a time within the group. Each button needs its own unique id (for the label) and its own value (what gets sent to the server when that option is chosen).
#Multi-line Text and Dropdowns
Two more essential form elements: <textarea> for longer free-form text (like a message or bio), and <select> for a dropdown list of fixed options.
<!-- Multi-line text area -->
<label for="bio">Short bio</label>
<textarea id="bio" name="bio" rows="4" placeholder="Tell us about yourself..."></textarea>
<!-- Dropdown select -->
<label for="country">Country</label>
<select id="country" name="country">
<option value="">-- Choose one --</option>
<option value="us">United States</option>
<option value="gb">United Kingdom</option>
<option value="ca">Canada</option>
</select>#Required and Placeholder Attributes
Two attributes you will use constantly: required makes a field mandatory (the browser blocks submission if it is empty), and placeholder shows ghost text inside the input as a hint. They are simple but very effective.
<form action="/contact" method="post">
<label for="name">Full name</label>
<input
type="text"
id="name"
name="name"
placeholder="Jane Smith"
required>
<label for="email">Email address</label>
<input
type="email"
id="email"
name="email"
placeholder="jane@example.com"
required>
<button type="submit">Send message</button>
</form>#The Button Element
A <button> inside a <form> defaults to type="submit", which triggers form submission. You can also set type="button" to prevent submission (useful when you add JavaScript later) or type="reset" to clear all fields. Always set the type explicitly so your intent is clear.
<button type="submit">Submit form</button>
<button type="reset">Clear all fields</button>
<button type="button">Just a button (no submit)</button>#Putting It All Together
<form action="/register" method="post">
<label for="fullName">Full name</label>
<input type="text" id="fullName" name="fullName"
placeholder="Jane Smith" required>
<label for="email">Email</label>
<input type="email" id="email" name="email"
placeholder="jane@example.com" required>
<label for="password">Password</label>
<input type="password" id="password" name="password"
placeholder="At least 8 characters" required>
<label for="age">Age</label>
<input type="number" id="age" name="age" min="13" max="120">
<fieldset>
<legend>I am a...</legend>
<input type="radio" id="learner" name="role" value="learner">
<label for="learner">Learner</label>
<input type="radio" id="teacher" name="role" value="teacher">
<label for="teacher">Teacher</label>
</fieldset>
<label for="bio">Bio (optional)</label>
<textarea id="bio" name="bio" rows="3"
placeholder="A little about you..."></textarea>
<input type="checkbox" id="newsletter" name="newsletter">
<label for="newsletter">Subscribe to newsletter</label>
<button type="submit">Create account</button>
</form>You have two radio buttons for 'Yes' and 'No'. What must they share so the browser treats them as a group (allowing only one to be selected)?
Key takeaways
- Wrap all form fields in <form> with action (destination) and method (GET or POST).
- Always pair every input with a <label> using matching for and id — it helps screen readers and improves usability.
- The type attribute on <input> (text, email, password, checkbox, radio, number) changes browser behavior and validation automatically.
- Use required to enforce mandatory fields and placeholder to show helpful hints inside inputs.
- Radio buttons must share the same name to function as a single-choice group; each needs its own id and value.
Complete this label/input pairing so that clicking the label focuses the text box and the value is sent to the server as 'username'. Fill in the attribute that connects the label to the input.
<label ="username">Username</label> <input type="text" id="username" name="username">
This code has a bug — the two radio buttons let the user select BOTH at once instead of only one. What's wrong?
<input type="radio" id="cat" name="catPet" value="cat">
<label for="cat">Cat person</label>
<input type="radio" id="dog" name="dogPet" value="dog">
<label for="dog">Dog person</label>Arrange these lines to build a valid form skeleton: a form that posts to /signup, containing a labelled email field, then a submit button.
<form action="/signup" method="post">
</form>
<label for="email">Email</label>
<input type="email" id="email" name="email">
<button type="submit">Sign Up</button>
How does the browser display and behave for this snippet?
<label for="bio">Short bio</label>
<textarea id="bio" name="bio" rows="4"
placeholder="Tell us about yourself..."></textarea>Build a short pizza order form. It should collect: the customer's name (text, required), their email (email, required), pizza size (radio buttons: Small, Medium, Large), extra toppings (at least two checkboxes, e.g. Mushrooms and Olives), any special instructions (textarea), and a Submit Order button.
Try it live — edit the code and hit Run to see it rendered: