Web Foundations
By Adam Roberts

Better web forms with HTML5, Part 3

By Adam Roberts

This is the third article in our series on building better web forms with HTML5. For the first and second articles visit Better web forms with HTML5, Part 1 and Better web forms with HTML5, Part 2 respectively.

In the last two lessons we have looked at why HTML5 is helpful for developers to build online forms and the HTML5 form attributes you will need to know. Let’s keep going and look at the new HTML5 input types and how you can use them.

HTML5 New Form Input Types

You’re probably already familiar with the input element’s type attribute. This is the attribute that determines what kind of form input will be presented to the user. If it is omitted — or, in the case of new input types and older browsers, not understood — it still works: the input will default to type="text". This is the key that makes HTML5 forms usable today. If you use a new input type, like email or search, older browsers will simply present users with a standard text field.

Our sign-up form currently uses four of the ten input types you’re familiar with: checkbox, text, password, and submit. Here’s the full list of types that were available before HTML5:

  • button
  • checkbox
  • file
  • hidden
  • image
  • password
  • radio
  • reset
  • submit
  • text

HTML5 gives us input types that provide for more data-specific UI elements and native data validation. HTML5 has a total of 13 new input types:

  • search
  • email
  • url
  • tel
  • datetime
  • date
  • month
  • week
  • time
  • datetime-local
  • number
  • range
  • color

Let’s look at each of these new types in detail, and see how we can put them to use.


The search input type (type="search") provides a search field—a one-line text input control for entering one or more search terms. The spec states:

The difference between the text state and the search state is primarily stylistic: on platforms where search fields are distinguished from regular text fields, the search state might result in an appearance consistent with the platform’s search fields rather than appearing like a regular text field.

Many browsers style search inputs in a manner consistent with the browser or the operating system’s search boxes. Some browsers have added the ability to clear the input with the click of a mouse, by providing an x icon once text is entered into the field. You can see this behavior in Chrome on Mac OS X in Figure 1.

Figure 1. The search input type is styled to resemble the operating system’s search fields

Figure 1. The search input type is styled to resemble the operating system’s search fields

Currently, only Chrome and Safari provide a button to clear the field. Opera 11 displays a rounded corner box without a control to clear the field, but switches to display a normal text field if any styling, such as a background color, is applied.

While you can still use type="text" for search fields, the new search type is a visual cue as to where the user needs to go to search the site, and provides an interface the user is accustomed to.

Here’s an example of how you’d use it:

<form id="search" method="get">
  <input type="search" id="s" name="s">
  <input type="submit" value="Search">

Since search, like all the new input types, appears as a regular text box in nonsupporting browsers, there’s no reason not to use it when appropriate.

Email Addresses

The email type (type="email") is, unsurprisingly, used for specifying one or more email addresses. It supports the Boolean multiple attribute, allowing for multiple, comma-separated email addresses.

Let’s change our form to use type="email" for the registrant’s email address:

<label for="email">My email address is</label>
<input type="email"  id="email" name="email">

If you change the input type from text to email, as we’ve done here, you’ll notice no visible change in the user interface; the input still looks like a plain text field. However, there are differences behind the scenes.

The change becomes apparent if you’re using an iOS device. When you focus on the email field, the iPhone, iPad, and iPod will all display a keyboard optimized for email entry (with a shortcut key for the @ symbol), as shown in Figure 2.

Figure 2. The email input type provides a specialized keyboard on iOS devices

Figure 2. The email input type provides a specialized keyboard on iOS devices

Firefox, Chrome, and Opera also provide error messaging for email inputs: if you try to submit a form with content unrecognizable as one or more email addresses, the browser will tell you what is wrong. The default error messages are shown in Figure 3.

Figure 3. Error messages for incorrectly formatted email addresses on Firefox 4 (left) and Opera 11 (right)

Figure 3. Error messages for incorrectly formatted email addresses on Firefox 4 (left) and Opera 11 (right)

Custom Validation Messages

Don’t like the error messages provided? In some browsers, you can set your own with .setCustomValidity(errorMsg). setCustomValidity takes as its only parameter the error message you want to provide. You can pass an empty string to setCustomValidity if you want to remove the error message entirely.

Unfortunately, while you can change the content of the message, you’re stuck with its appearance, at least for now.


The url input (type="url") is used for specifying a web address. Much like email, it will display as a normal text field. On many touch screens, the on-screen keyboard displayed will be optimized for web address entry, with a forward slash (/) and a “.com” shortcut key.

Let’s update our registration form to use the url input type:

<label for="url">My website is located at:</label>
<input type="url" id="url" name="url">

Opera, Firefox, and WebKit support the url input type, reporting the input as invalid if the URL is incorrectly formatted. Only the general format of a URL is validated, so, for example, q://example.xyz will be considered valid, even though q:// isn’t a real protocol and .xyz isn’t a real top-level domain. As such, if you want the value entered to conform to a more specific format, provide information in your label (or in a placeholder) to let your users know, and use the pattern attribute to ensure that it’s correct—we’ll cover pattern in detail later in this chapter.


When we refer to WebKit in this book, we’re referring to browsers that use the WebKit rendering engine. This includes Safari (both on the desktop and on iOS), Google Chrome, the Android browser, and a number of other mobile browsers. You can find more information about the WebKit open source project at http://www.webkit.org.

Telephone Numbers

For telephone numbers, use the tel input type (type="tel"). Unlike the url and email types, the tel type doesn’t enforce a particular syntax or pattern. Letters and numbers — indeed, any characters other than new lines or carriage returns — are valid. There’s a good reason for this: all over the world countries have different types of valid phone numbers, with various lengths and punctuation, so it would be impossible to specify a single format as standard. For example, in the USA, +1(415)555-1212 is just as well understood as 415.555.1212.

You can encourage a particular format by including a placeholder with the correct syntax, or a comment after the input with an example. Additionally, you can stipulate a format by using the pattern attribute or the setCustomValidity method to provide for client-side validation.


The number type (type="number") provides an input for entering a number. Usually, this is a “spinner” box, where you can either enter a number or click on the up or down arrows to select a number.

Let’s change our quantity field to use the number input type:

<label for="quantity">I would like to receive <input type="number" name="quantity" id="quantity"> copies of <cite>The HTML5 Herald</cite></label>

Figure 4. shows what this looks like in Opera.

Figure 4. The number input seen in Opera

Figure 4. The number input seen in Opera

The number input has min and max attributes to specify the minimum and maximum values allowed. We highly recommend that you use these, otherwise the up and down arrows might lead to different (and very odd) values depending on the browser.

When is a number not a number?

There will be times when you may think you want to use number, when in reality another input type is more appropriate. For example, it might seem to make sense that a street address should be a number. But think about it: would you want to click the spinner box all the way up to 34154? More importantly, many street numbers have non-numeric portions: think 24½ or 36B, neither of which work with the number input type.

Additionally, account numbers may be a mixture of letters and numbers, or have dashes. If you know the pattern of your number, use the pattern attribute. Just remember not to use number if the range is extensive or the number could contain non-numeric characters and the field is required. If the field is optional, you might want to use number anyway, in order to prompt the number keyboard as the default on touchscreen devices.

If you do decide that number is the way to go, remember also that the pattern attribute is unsupported in the number type. In other words, if the browser supports the number type, that supersedes any pattern. That said, feel free to include a pattern, in case the browser supports pattern but not the number input type.

You can also provide a step attribute, which determines the increment by which the number steps up or down when clicking the up and down arrows. The min, max, and step attributes are supported in Opera and WebKit.

On many touchscreen devices, focusing on a number input type will bring up a number touch pad (rather than a full keyboard).


The range input type (type=”range”) displays a slider control in browsers that support it (currently Opera and WebKit). As with the number type, it allows the min,max, and step attributes. The difference between number and range, according to the spec, is that the exact value of the number is unimportant with range. It’s ideal for inputs where you want an imprecise number; for example, a customer satisfaction survey asking clients to rate aspects of the service they received.

Let’s change our registration form to use the range input type. The field asking users to rate their knowledge of HTML5 on a scale of 1 to 10 is perfect:

<label for="rating">On a scale of 1 to 10, my knowledge of HTML5 is:</label>
<input type="range" min="1" max="10" name="rating" type="range">

The step attribute defaults to 1, so it’s not required. Figure 5 shows what this input type looks like in Safari.

Figure 5. The range input type in Chrome

Figure 5. The range input type in Chrome

The default value of a range is the midpoint of the slider—in other words, halfway between the minimum and the maximum.

The spec allows for a reversed slider (with values from right to left instead of from left to right) if the maximum specified is less than the minimum; however, currently no browsers support this.


The color input type (type="color") provides the user with a color picker—or at least it does in Opera (and, surprisingly, in the built-in browser on newer BlackBerry smartphones). The color picker should return a hexadecimal RGB color value, such as #FF3300.

Until this input type is fully supported, if you want to use a color input, provide placeholder text indicating that a hexadecimal RGB color format is required, and use the pattern attribute to restrict the entry to only valid hexadecimal color values.

We don’t use color in our form, but, if we did, it would look a little like this:

<label for="clr">Color: </label>
<input id="clr" name="clr" type="text" placeholder="#FFFFFF" pattern="#(?:[0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})" required>

The resulting color picker is shown in Figure 6. Clicking the Other… button brings up a full color wheel, allowing the user to select any hexadecimal color value.

Figure 6. Opera’s color picker control for the color input type

Figure 6. Opera’s color picker control for the color input type

WebKit browsers support the color input type as well, and can indicate whether the color is valid, but don’t provide a color picker… yet.

Dates and Times

There are several new date and time input types, including date, datetime, datetime-local, month, time, and week. All date and time inputs accept data formatted according to the ISO 8601 standard.

This comprises the date (year, month, and day), but no time; for example, 2004-06-24.

Only includes the year and month; for example, 2012-12.

This covers the year and week number (from 1 to 52); for example, 2011-W01 or 2012-W52.

A time of day, using the military format (24-hour clock); for example, 22:00 instead of 10.00 p.m.

This includes both the date and time, separated by a “T”, and followed by either a “Z” to represent UTC (Coordinated Universal Time), or by a time zone specified with a + or – character. For example, “2011-03-17T10:45-5:00″ represents 10:45am on the 17th of March, 2011, in the UTC minus 5 hours time zone (Eastern Standard Time).

Identical to datetime, except that it omits the timezone.

The most commonly used of these types is date. The specifications call for the browser to display a date control, yet at the time of writing, only Opera does this by providing a calendar control.

Let’s change our subscription start date field to use the date input type:

<label for="startdate">Please start my subscription on:</label>
<input type="date" min="1904-03-17" max="1904-05-17" id="startdate" name="startdate" required aria-required="true" placeholder="1911-03-17">

Now, we’ll have a calendar control when we view our form in Opera, as shown in Figure 7. Unfortunately, it’s unable to be styled with CSS at present.

Figure 7. Opera’s date picker for date, datetime, datetime-local, week, and month input types

Figure 7. Opera’s date picker for date, datetime, datetime-local, week, and month input types

For the month and week types, Opera displays the same date picker, but only allows the user to select full months or weeks. In those cases, individual days are unable to be selected; instead, clicking on a day selects the whole month or week.

Currently, WebKit provides some support for the date input type, providing a user interface similar to the number type, with up and down arrows. Safari behaves a little oddly when it comes to this control; the default value is the very first day of the Gregorian calendar: 1582-10-15. The default in Chrome is 0001-01-01, and the maximum is 275760-09-13. Opera functions more predictably, with the default value being the current date. Because of these oddities, we highly recommend including a minimum and maximum when using any of the date-based input types (all those listed above, except time). As with number, this is done with the min and max attributes.

The placeholder attribute we added to our start date field earlier is made redundant in Opera by the date picker interface, but it makes sense to leave it in place to guide users of other browsers.

Eventually, when all browsers support the UI of all the new input types, the placeholder attribute will only be relevant on text, search, URL, telephone, email, and password types. Until then, placeholders are a good way to hint to your users what kind of data is expected in those fields—remember that they’ll just look like regular text fields in nonsupporting browsers.

Dynamic Dates

In our example above, we hardcoded the min and max values into our HTML. If, for example, you wanted the minimum to be the day after the current date (this makes sense for a newspaper subscription start date), this would require updating the HTML every day. The best thing to do is dynamically generate the minimum and maximum allowed dates on the server side. A little PHP can go a long way:

function daysFromNow($days){
  $added = ($days * 24 * 3600) + time();
  echo(date("Y-m-d", $added));

In our markup where we had static dates, we now dynamically create them with the above function:

  <label for="startdate">Please start my subscription on:</label>
  <input type="date" min="<?php daysFromNow(1); ?>" max="<?php daysFromNow(60); ?>" id="startdate" name="startdate" required aria-required="true" placeholder="1911-03-17">

This way, the user is limited to entering dates that make sense in the context of the form.

You can also include the step attribute with the date and time input types. For example, step="6" on month will limit the user to selecting either January or July. On time and datetime inputs, the step attribute must be expressed in seconds, so step="900" on the time input type will cause the input to step in increments of 15 minutes.

Other New Form Controls in HTML5

We’ve covered the new values for the input element’s type attribute, along with some attributes that are valid on most form elements. But HTML5 web forms still have more to offer us! There are four new form elements in HTML5: output, keygen, progress, and meter. We covered progress and meter in the last chapter, since they’re often useful outside of forms, so let’s take a look at the other two elements.

The output Element

The purpose of the output element is to accept and display the result of a calculation. The output element should be used when the user can see the value, but not directly manipulate it, and when the value can be derived from other values entered in the form. An example use might be the total cost calculated after shipping and taxes in a shopping cart.

The output element’s value is contained between the opening and closing tags. Generally, it will make sense to use JavaScript in the browser to update this value. The output element has a for attribute, which is used to reference the ids of form fields whose values went into the calculation of the output element’s value.

It’s worth noting that the output element’s name and value are submitted along with the form.

The keygen Element

The keygen element is a control for generating a public-private keypair and for submitting the public key from that key pair. Opera, WebKit, and Firefox all support this element, rendering it as a drop-down menu with options for the length of the generated keys; all provide different options, though.

The keygen element introduces two new attributes: the challenge attribute specifies a string that is submitted along with the public key, and the keytype attribute specifies the type of key generated. At the time of writing, the only supported keytype value is rsa, a common algorithm used in public-key cryptography.

In the next instalment we are going to look at the changes that have occurred with existing form controls and attributes.

For the final article in this series, visit Better web forms with HTML, Part 4

This is an excerpt from HTML5 & CSS3 for the Real World, by Alexis Goldstein, Louis Lazaris & Estelle Weyl.