Making forms in HTML isn’t too complex but without a backend server language like PHP or Python (or maybe a little JavaScript) we can’t actually do anything with the form itself.

Form setup

There are a few important things to remember about form tags.

<form action="thanks.html" method="post">
  • The action attribute is the URL to where the form’s information should be submitted—but we need a programming language to do something with it.
  • The method attribute is either get or post—should most often be “post”. (This matters most to backend developers.)

Inputs and labels

Inside a form we can create a bunch of inputs—the things people interact with and submit their information to.

All input elements must have a label element associated with them, primarily for accessibility reasons but also as a way to denote what content should be entered into the field.

The input element needs an ID on it, then the label points to the ID using it’s for attribute.

<form action="thanks.html" method="post">
  <!-- Labels are associated with inputs using the for and id attributes -->
  <label for="name">Name</label>
  <input id="name">


Input types

There are lots of different input types to use in forms—the default is text.

<!-- type="text" is the default for all elements and can be left off -->
<input type="text">
  • number — for accepting numbers
  • email — for accepting valid e-mail addresses
  • url — for valid website URLs
  • password — masks the text that’s being entered with bullets
  • tel — for telephone numbers
  • time — for accepting time: hours, minutes, seconds
  • date — for accepting dates; a calendar picker
  • range — for selecting from a range of numbers
  • color — for picking a specific colour
  • file — for allowing the upload of files
  • search — for specifying the input as a search field

Some examples:

<label for="email">E-mail address</label>
<input type="email" id="email">

<label for="homepage">Homepage</label>
<input type="url" id="homepage">

<label for="fav-color">Favourite colour</label>
<input type="color" id="fav-color">

Other attributes

Some elements can have other attributes to control what content is allowed to be entered into the field.

  • min — For specifying a minimum value, for ranges and numbers
  • max — For specifying a maximum value, for ranges and numbers
  • step — For specifying a jump value for each increment, for ranges and numbers
  Would allow any number between 0 and 1, in increments of 0.1
  e.g. 0, 0.1, 0.2, 0.3 ... 0.9, 1.0
<input type="number" min="0" max="1" step="0.1">


The placeholder attribute can be used to put example text into an element—but should never be used as a replacement for the label.

<input type="url" placeholder="">


Other input types

There are some other input types that can be used in forms for more complex interactions.


An alternative to <input type="text"> that allows multiple lines and longer text.

<label for="message">Message</label>
<textarea id="message"></textarea>

Select boxes

Select boxes, aka dropdown boxes, allow a user to pick one option of many.

<label for="province">Province</label>
<select id="province">

Options elements can be grouped together using the <optgroup> tag. The label="…" attribute is used to show a non-selectable heading for the group.

<label for="province">Province or State</label>
<select id="province">
  <optgroup label="Canada">
  <optgroup label="United States">
    <option>New York</option>


Checkboxes allow a selection of multiple items out of a few possiblities.

<input type="checkbox" id="apato">
<label for="apato">Apatosaurus</label>

In checkboxes (and radio buttons) it’s most common to have the label come after the input element.

If you want the checkbox to be checked by default use the checked attribute. This applies to radio buttons too.

<input type="checkbox" id="apato" checked>
<label for="apato">Apatosaurus</label>

Radio buttons

Radio buttons allow users to select a single option out of many, similar to a select box.

  <legend>What’s your favourite colour?</legend>

  <input type="radio" id="green" name="fav-color">
  <label for="green">Green</label>

  <input type="radio" id="light-green" name="fav-color">
  <label for="light-green">Light Green</label>

  <input type="radio" id="dark-green" name="fav-color">
  <label for="dark-green">Dark Green</label>

The way to group a bunch of radio buttons together, so they work as a single group is to give them all the same name, like name="fav-color".


Above, we’re using the <fieldset> element to group radio buttons together semantically. The fieldset can be used to group any inputs together in a form that logically belong together.

Groups of radio buttons and checkboxes should always be surrounded by fieldsets.

Here’s an example of grouping address inputs together:

  <legend>Mailing Address</legend>

    <label for="street-address">Street Address</label>
    <input id="street-address">
    <label for="city">City</label>
    <input id="city">
    <label for="country">Country</label>
    <input id="country">
    <label for="postal-code">Postal Code</label>
    <input id="postal-code">


All forms need to have buttons otherwise the form’s information can’t be sent.

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

Most often the button’s type should be set to “submit”. But if you don’t want it to submit the form and control the button with JavaScript, leave the type attribute off.

Styling forms and inputs

When it comes to styling inputs and forms, the most important thing to remember that they are just plain old HTML elements. They can have borders, paddings, margins, colors, fonts, display—anything.

Making forms functional

There’s a few small things to can to to make our forms slightly more functional without a backend server.


The required attribute can be added to fields to force the user to type something into the field. If the field type is something specific like email it will enforce a properly formatted email address.

<label for="email">E-mail address</label>
<input type="email" id="email" required>


As seen above we can control the max and min for numbers—we can do something similar for text fields with the maxlength and minlength attributes.

<label for="password">Password</label>
<input type="password" minlength="6" id="password">


The pattern attribute can be used to restrict the format of the text entered into a field. It uses regular expressions.

<label for="postalcode">Postal code</label>
<input type="text" pattern="[A-Za-z][0-9][A-Za-z] ?[0-9][A-Za-z][0-9]" id="postalcode">

The above regular expression looks for a valid Canadian postal code.


Form submission without a server

If you’re creating a static website, without wanting to have to write backend PHP, etc. to make your website function, there’s a few great services you can use.

These services work in a fashion similar to this:

  1. You create a form, that points to their service.
  2. The user submits the form.
  3. The data is sent to the service’s website.
  4. The service composes an email and sends it to you.
  5. The service redirects the user back to your website to display a message.

The services work really well for simple information collection, but aren’t great for complex registration forms, etc.

Form services

Video list

  1. Forms: Introduction
  2. Forms: Contact form
  3. Forms: Styling
  4. Forms: Input types
  5. Forms: Checkboxes, radio buttons & fieldsets