← Back to Chapters

HTML Forms

? HTML Forms

⚡ Quick Overview

HTML forms collect user input and send it to a server. You build robust forms by pairing inputs with clear labels, choosing the right input types, using built-in validation, and providing helpful hint/error text. Accessible forms not only look good but also work well with screen readers, keyboards, and mobile devices.

? Key Concepts

  • <form> wraps all controls and defines the action URL and HTTP method (get / post).
  • <label> connects to an input with matching for (on label) and id (on input) for accessibility.
  • Inputs support semantic types like text, email, password, number, date, checkbox, radio, etc.
  • <fieldset> and <legend> group related controls with a meaningful title.
  • Validation uses attributes such as required, minlength, pattern, as well as appropriate types.
  • Help text is linked with aria-describedby to explain what a field expects.

? Basic Form Structure

? View Basic Syntax
<!-- Simple contact form skeleton -->
<form action="/submit" method="post">
  <label for="name">Full name</label>
  <input id="name" name="name" type="text" required>

  <label for="email">Email</label>
  <input id="email" name="email" type="email" required>

  <button type="submit">Send</button>
</form>

In real projects you often group inputs into sections (contact info, preferences, message, etc.) and add more attributes for validation and usability.

? Accessible Multi-Field Form Example

? View Full Form Markup
<form action="/submit" method="post" autocomplete="on">
  <fieldset>
    <legend>Contact details</legend>

    <label for="name" class="req">Full name</label>
    <input id="name" name="name" type="text" required autocomplete="name">

    <div class="row">
      <div>
        <label for="email" class="req">Email</label>
        <input id="email" name="email" type="email" required autocomplete="email">
      </div>

      <div>
        <label for="phone">Phone</label>
        <input id="phone" name="phone" type="text" inputmode="tel" autocomplete="tel">
      </div>
    </div>

    <label for="password" class="req">Password</label>
    <input
      id="password"
      name="password"
      type="password"
      required
      minlength="8"
      pattern="(?=.*[A-Za-z])(?=.*\d).{8,}"
      aria-describedby="pwHelp">

    <div id="pwHelp" class="help">At least 8 characters, with letters and a number.</div>
  </fieldset>

  <fieldset>
    <legend>Preferences</legend>

    <label for="role" class="req">Role</label>
    <select id="role" name="role" required>
      <option value="" disabled selected>Select a role</option>
      <option>Student</option>
      <option>Educator</option>
      <option>Developer</option>
      <option>Other</option>
    </select>

    <div class="inline" role="group" aria-labelledby="contactPref">
      <span id="contactPref" class="sr-only">Preferred contact method</span>
      <label><input type="radio" name="contact" value="email" checked> Email</label>
      <label><input type="radio" name="contact" value="phone"> Phone</label>
    </div>

    <label>
      <input type="checkbox" name="subscribe" value="yes">
      Subscribe to updates
    </label>
  </fieldset>

  <label for="message">
    Message <span class="pill">optional</span>
  </label>
  <textarea
    id="message"
    name="message"
    rows="3"
    maxlength="500"
    aria-describedby="msgHelp"></textarea>
  <div id="msgHelp" class="help">Max 500 characters.</div>

  <div class="actions">
    <button type="submit">Submit</button>
    <button type="reset">Reset</button>
  </div>
</form>

? Live Output / Interactive Demo

?️ Form Preview

This demo form is captured locally with JavaScript to show what data would be sent to a server. Try filling it out and clicking Submit.

Contact details
At least 8 characters, with letters and a number.
Preferences
Preferred contact method
Max 500 characters.
 

? Tips & Best Practices

  • Always pair inputs with <label> elements using matching for/id attributes.
  • Include name attributes on all fields you want submitted to the server.
  • Use semantic input types (email, tel, date) for better validation and mobile keyboards.
  • Group related fields with <fieldset> and describe the group using <legend>.
  • Add autocomplete attributes (name, email, tel, etc.) to improve UX.
  • Prefer built-in HTML validation first; then enhance with JavaScript only when needed.
  • Use help text connected via aria-describedby for complex requirements (password rules, limits, etc.).
  • On the server, always validate again and protect against CSRF/XSS — client-side checks alone are not secure.

? Try It Yourself

  • Add a number input for age with min and max, and a date input for date of birth.
  • Create a checkbox group named topics[] (e.g., HTML, CSS, JS) and submit multiple selected values.
  • Use the setCustomValidity() API in JavaScript to display a custom error message when the password does not meet your rules.
  • Add a small help link inside your form that opens in a new tab using target="_blank" and pair it with rel="noopener".

? Summary

  • HTML forms collect and submit user data using the <form> element, inputs, labels, and buttons.
  • Labels, fieldsets, and legends make forms more accessible and easier to understand.
  • Semantic input types and validation attributes reduce JavaScript and improve usability.
  • Use help text and ARIA attributes to clarify requirements and errors for all users.
  • Always validate data again on the server and treat client-side checks as a convenience, not security.