Forms & SemanticsBeginner8 min07 / 8

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).

A bare-bones form skeleton. action points to the server endpoint; method="post" keeps data out of the URL.
<form action="/signup" method="post">
  <!-- inputs go here -->
  <button type="submit">Sign Up</button>
</form>
Think of it like

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.

The for attribute on <label> must match the id on <input>. The name attribute is what gets sent to the server.
<label for="username">Username</label>
<input type="text" id="username" name="username" placeholder="e.g. coolcoder42">
Common mistake

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:

All input types — same tag, very different behavior. Radio buttons share the same name to form a group.
<!-- 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>
Tip

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.

textarea is NOT self-closing — it needs an explicit closing tag. The empty-value first <option> acts as a prompt.
<!-- 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.

required is a boolean attribute — just its presence is enough. No value needed.
<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.

Three flavors of <button>. The submit type is the default inside a form.
<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

A realistic registration form using everything covered in this lesson. <fieldset> and <legend> group related inputs semantically.
<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>
Quick check

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.
Practice challenges
Test yourself · earn XP
0/4
Fill in the blank#1

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">
Fix the bug#2

This code has a bug — the two radio buttons let the user select BOTH at once instead of only one. What's wrong?

fix-bug
<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>
Reorder the lines#3

Arrange these lines to build a valid form skeleton: a form that posts to /signup, containing a labelled email field, then a submit button.

1
<form action="/signup" method="post">
2
</form>
3
  <label for="email">Email</label>
4
  <input type="email" id="email" name="email">
5
  <button type="submit">Sign Up</button>
Predict the output#4

How does the browser display and behave for this snippet?

predict-output
<label for="bio">Short bio</label>
<textarea id="bio" name="bio" rows="4"
          placeholder="Tell us about yourself..."></textarea>
Your turn
Practice exercise

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:

solution.html · editable