🚀 New batches open: Advanced Excel • Power BI • SQL • AI for Analytics — Book a free demo

Day 5 — Forms, inputs and labels

Forms are where your page stops being a document and starts being useful. They are also where accessibility is most often thrown away.

The shape of a form

<form>
  <p>
    <label for="name">Your name</label><br>
    <input type="text" id="name" name="name">
  </p>
  <p>
    <button type="submit">Send</button>
  </p>
</form>
label for = input id. Always. This is the single most important line in this lesson. When they match:
  • Clicking the label focuses the field - a much bigger tap target on a phone.
  • A screen reader announces "Your name, edit text" instead of just "edit text".
Delete the id in the box above and the Check tab tells you no label can reach the field. Placeholder text is not a label - it vanishes the moment somebody types.

Input types

The type attribute does real work. On a phone it changes the keyboard that comes up, and the browser validates the value for free.

<form>
  <p>
    <label for="email">Email</label><br>
    <input type="email" id="email" name="email" placeholder="you@example.com">
  </p>
  <p>
    <label for="phone">Mobile</label><br>
    <input type="tel" id="phone" name="phone" maxlength="10">
  </p>
  <p>
    <label for="fee">Budget</label><br>
    <input type="number" id="fee" name="fee" min="0" max="100000" step="500">
  </p>
  <p>
    <label for="start">Preferred start date</label><br>
    <input type="date" id="start" name="start">
  </p>
  <p>
    <label for="pw">Password</label><br>
    <input type="password" id="pw" name="pw">
  </p>
</form>
typeWhat you get
textPlain text, the default
emailAn @ keyboard, and a format check on submit
telThe number pad on a phone
numberSpinners, plus min, max and step
dateA date picker
passwordDots instead of characters
checkboxIndependent yes or no
radioPick exactly one from a group
fileA file picker
hiddenCarried along, never shown

Required, and free validation

<form>
  <p>
    <label for="n2">Name</label><br>
    <input type="text" id="n2" name="name" required minlength="2">
  </p>
  <p>
    <label for="e2">Email</label><br>
    <input type="email" id="e2" name="email" required>
  </p>
  <p>
    <label for="p2">10-digit mobile</label><br>
    <input type="tel" id="p2" name="phone" required pattern="[0-9]{10}">
  </p>
  <p><button type="submit">Book a demo</button></p>
</form>
Browser validation is a convenience, not security Anyone can strip required out with the developer tools in three seconds, or skip the page entirely and post straight to your server. Always validate again on the server. HTML validation exists to be kind to honest users, not to stop dishonest ones.

Choosing from a list

<form>
  <p>
    <label for="course">Which course?</label><br>
    <select id="course" name="course">
      <option value="">-- choose --</option>
      <option value="excel">Advanced Excel</option>
      <option value="powerbi">Power BI</option>
      <option value="sql" selected>SQL</option>
    </select>
  </p>
</form>

value is what gets sent to the server. The text between the tags is what the human reads. They do not have to match.

Radio buttons and checkboxes

Radios in the same group must share the same name. That is what makes them mutually exclusive - not their position on the page.

<form>
  <fieldset>
    <legend>Batch preference</legend>
    <p>
      <input type="radio" id="wd" name="batch" value="weekday" checked>
      <label for="wd">Weekday</label>
    </p>
    <p>
      <input type="radio" id="we" name="batch" value="weekend">
      <label for="we">Weekend</label>
    </p>
  </fieldset>

  <p>
    <input type="checkbox" id="terms" name="terms" required>
    <label for="terms">I agree to the terms</label>
  </p>
</form>

Change the second radio’s name to something else and run it - now both can be selected at once, because they are no longer one group.

<fieldset> and <legend> group related controls and give the group a name a screen reader can announce. Use them for every radio group.

Longer text

<form>
  <p>
    <label for="goal">What do you want to achieve?</label><br>
    <textarea id="goal" name="goal" rows="4" cols="40"></textarea>
  </p>
</form>
textarea always needs a closing tag Even when it is empty, and there is no value attribute - whatever sits between the tags is the starting content. Put a newline in there by accident and it becomes part of the value.

Where the form goes

<form action="/api/save.php" method="post">

GET puts the values in the URL. Good for a search box, because the result is linkable. POST sends them in the body. Use POST for anything that changes data, and for anything private - a password in a URL ends up in browser history and server logs.

Try these yourself

  1. Build an enquiry form with name, email, 10-digit mobile and a course dropdown.
  2. Add a label to every field and check the Check tab is clean.
  3. Add a radio group for weekday or weekend, wrapped in a fieldset with a legend.
  4. Make the email required and try submitting the preview with it empty.
  5. Explain why HTML validation does not remove the need for server-side validation.