On this page

Complete and functional HTML forms

14 min read TextCh. 4 — Forms

Anatomy of a form

An HTML form is an interactive container that collects user data and sends it to a server. It consists of the <form> element and its internal controls.

The form element

<form action="/process" method="post">
  <!-- Form controls -->
</form>

Main attributes of <form>:

Attribute Description
action URL where the data is sent
method get (data in URL) or post (data in the body)
enctype Encoding type (needed for files)
novalidate Disables native browser validation

Input types

HTML5 introduced many specialized <input> types that provide optimized mobile keyboards and automatic validation:

Text and personal data

<input type="text" name="name" placeholder="Your name">
<input type="email" name="email" placeholder="[email protected]">
<input type="password" name="password" placeholder="Your password">
<input type="tel" name="phone" placeholder="+1 555-0123">
<input type="url" name="website" placeholder="https://yoursite.com">

Numbers and ranges

<input type="number" name="age" min="18" max="120" step="1">
<input type="range" name="volume" min="0" max="100" value="50">

Dates and time

<input type="date" name="date">
<input type="time" name="time">
<input type="datetime-local" name="datetime">
<input type="month" name="month">
<input type="week" name="week">

Other types

<input type="color" name="favorite-color" value="#ff5500">
<input type="file" name="document" accept=".pdf,.doc">
<input type="hidden" name="token" value="abc123">
<input type="search" name="search" placeholder="Search...">

The select element (dropdown lists)

The <select> element allows choosing one or more options from a list:

<!-- Single selection -->
<label for="country">Country</label>
<select id="country" name="country">
  <option value="">Select a country</option>
  <option value="us">United States</option>
  <option value="uk">United Kingdom</option>
  <option value="ca">Canada</option>
  <option value="au">Australia</option>
</select>

You can group options with <optgroup>:

<select id="language" name="language">
  <optgroup label="Frontend">
    <option value="html">HTML</option>
    <option value="css">CSS</option>
    <option value="js">JavaScript</option>
  </optgroup>
  <optgroup label="Backend">
    <option value="python">Python</option>
    <option value="node">Node.js</option>
  </optgroup>
</select>

Textarea (multiline text)

For extended text fields, use <textarea>:

<label for="comment">Your comment</label>
<textarea id="comment" name="comment" rows="5" cols="40"
  maxlength="500" placeholder="Write your comment here..."></textarea>

Unlike <input>, <textarea> has a closing tag and its default content goes between the tags.

Checkboxes and radio buttons

Checkboxes (multiple selection)

<fieldset>
  <legend>Interests (choose all that apply)</legend>
  <label>
    <input type="checkbox" name="interests" value="html"> HTML
  </label>
  <label>
    <input type="checkbox" name="interests" value="css"> CSS
  </label>
  <label>
    <input type="checkbox" name="interests" value="js"> JavaScript
  </label>
</fieldset>

Radio buttons (single selection)

<fieldset>
  <legend>Experience level</legend>
  <label>
    <input type="radio" name="level" value="beginner"> Beginner
  </label>
  <label>
    <input type="radio" name="level" value="intermediate"> Intermediate
  </label>
  <label>
    <input type="radio" name="level" value="advanced"> Advanced
  </label>
</fieldset>

All radio buttons in the same group must share the same name attribute. Only one can be selected at a time.

Fieldset and legend

<fieldset> groups related fields and <legend> provides a label for the group. This is especially important for accessibility:

<fieldset>
  <legend>Shipping address</legend>
  <label for="street">Street</label>
  <input type="text" id="street" name="street">
  <label for="city">City</label>
  <input type="text" id="city" name="city">
  <label for="zip">Zip code</label>
  <input type="text" id="zip" name="zip">
</fieldset>

Form buttons

HTML offers three types of buttons within forms:

<!-- Submits the form -->
<button type="submit">Submit</button>

<!-- Resets all fields to their initial values -->
<button type="reset">Clear</button>

<!-- Generic button (does not submit or reset) -->
<button type="button">Custom action</button>

Always specify the type attribute on buttons. If you omit it, the button acts as submit by default, which can accidentally submit forms.

Datalist (autocomplete suggestions)

The <datalist> element provides a list of suggestions for an <input>, combining the flexibility of a text field with the convenience of a list:

<label for="framework">Favorite framework</label>
<input type="text" id="framework" name="framework" list="frameworks">
<datalist id="frameworks">
  <option value="Angular">
  <option value="React">
  <option value="Vue">
  <option value="Svelte">
</datalist>

The user can type freely or choose from the suggestions.

Practice

  1. Create a registration form: Build a form with method="post" that includes text fields, email, date, a <select>, a <textarea>, checkboxes, and radio buttons. Group related fields with <fieldset> and <legend>.
  2. Use datalist for suggestions: Add a text field with a <datalist> that offers at least 5 autocomplete suggestions.
  3. Experiment with input types: Create a test form with type="color", type="range", type="date", type="number", and type="file". Observe how the browser renders each one.

In the next lesson, we will learn how to validate forms using HTML5's native capabilities.

The autocomplete attribute
Use the autocomplete attribute with standard values like "name", "email", "tel", "street-address", etc. This allows the browser to autofill fields, improving the user experience especially on mobile devices.
Never use GET only
Do not send sensitive data (passwords, personal information) with method="get", as the data is visible in the URL. Use method="post" for private data.
html
<form action="/api/register" method="post">
  <h2>Create account</h2>

  <fieldset>
    <legend>Personal information</legend>

    <div>
      <label for="full-name">Full name *</label>
      <input type="text" id="full-name" name="fullName"
        required autocomplete="name"
        placeholder="e.g. Anna Garcia Lopez">
    </div>

    <div>
      <label for="email">Email address *</label>
      <input type="email" id="email" name="email"
        required autocomplete="email"
        placeholder="[email protected]">
    </div>

    <div>
      <label for="birth-date">Date of birth</label>
      <input type="date" id="birth-date" name="birthDate"
        min="1940-01-01" max="2010-12-31">
    </div>
  </fieldset>

  <fieldset>
    <legend>Preferences</legend>

    <div>
      <label for="level">Experience level</label>
      <select id="level" name="level">
        <option value="">Select a level</option>
        <option value="beginner">Beginner</option>
        <option value="intermediate">Intermediate</option>
        <option value="advanced">Advanced</option>
      </select>
    </div>

    <div>
      <label for="bio">About you</label>
      <textarea id="bio" name="bio" rows="4"
        maxlength="300"
        placeholder="Tell us a bit about yourself..."></textarea>
    </div>

    <div>
      <label>
        <input type="checkbox" name="newsletter" value="yes">
        I want to receive updates by email
      </label>
    </div>
  </fieldset>

  <button type="submit">Create my account</button>
  <button type="reset">Clear form</button>
</form>