Sign up for a free trial of our self-paced courses.

HTML5 Tutorial

HTML5 Forms

The promise of HTML5 forms is great - richer, more meaningful, and backward-compatible forms that are consistent across browsers and include built-in client-side validation (read, no need for JavaScript for form validation).

The current reality is that, while no browser (with the exception of iOS's Safari on iPhone) offers full support for all HTML5 form features, recent versions of all browsers do offer considerable implementation of new features. There are many things you can do now to take advantage of new features without causing any harm in the non-supporting browsers.

So let's dig in and learn how to use the new HTML5 form features.

Lesson Goals

  • Learn about Modernizr, the JavaScript library for testing for HTML5 support.
  • Learn about HTML5's new form fields and attributes.
  • Learn about new types of inputs in HTML5.
  • Learn about built-in HTML5 form validation.
  • Learn about the new HTML5 output, progress and meter elements.

Modernizr

Before we get into HTML5 forms, we will re-introduce you to a great little JavaScript library called Modernizr. Modernizr is used to check the browser for feature support so you can write code like this:

if (Modernizr.xyzFeature) { //do this; } else { //do something different }

We have included it in the html5-common folder in the root of the class files. Here's an example of how you can check for the new email input type:

Code Sample:

html5-forms/Demos/modernizr.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
<script src="../../html5-common/modernizr.min.js" type="text/javascript"></script>
<script>
	if (Modernizr.inputtypes.email) {
		alert("woohoo!");	
	} else {
		alert("boohoo!");	
	}
</script>
---- C O D E   O M I T T E D ----

To see which HTML5 features it supports, open html5-forms/Demos/modernizr-full-check.html in your browser.

We use modernizr in some of the demos in this lesson.

New Input Types

HTML5 introduces thirteen new input types:

  1. search
  2. tel
  3. url
  4. email
  5. datetime
  6. date
  7. month
  8. week
  9. time
  10. datetime-local
  11. number
  12. range
  13. color

While no desktop browser implements all of the new HTML5 input types, most current desktop browsers implement most of the features; support on mobile browsers in generally better than on desktop. Visit http://www.findmebyip.com/litmus to see the current state of browser support for these input types.

The good news is that major browsers all fall back to type="text" when they don't recognize an input type.

search

The new HTML5 search input type is supported by the latest version of all browsers.

Most input fields are meant to be filled out only one time and then submitted for processing. But a search box is a bit different. For example, consider Microsoft Word 2010's search box:

Notice the x used for clearing the box. If you look at search boxes in other applications, you'll notice many of them provide a simple way to clear the text. HTML5 browsers that support the search input type are taking the same approach. For example, here's Chrome's search box: Note that the x doesn't show up until you have entered some text into the field.

tel

The new HTML5 tel input type is supported by the latest version of all browsers.

On desktop browsers, you don't really gain anything by using the tel input type. As telephone numbers can come in all different formats, there are no constraints on what can be entered here. You could, however, add your own custom validation to all telephone inputs and use the type="tel" as a means of finding them.

Also, user agents are free to provide a different/better means for filling out input fields based on their type. For example, the iPhone provides a more appropriate interface (presenting the user with the phone keypad) for filling out fields of the tel type:

url and email

The new HTML5 url and email input types are supported by the latest version of all browsers.

Browsers can provide validation for type="url" fields to make sure the user enters a valid URL.

Also, like with type="tel", user agents are free to provide a different/better means for entering URLs and email addresses.

For example, for url types the iPhone provides keys for ".", "/" and ".com" and does not provide a "space" key, as spaces are not allowed in URLs:

For emails, the iPhone provides "@" and "." keys: For some reason, it does not provide a ".com" key.

Interestingly enough, the iPhone also provides a "space" key for emails. This is because email input types can include a multiple attribute, which, when included, allows users to enter multiple emails delimited by spaces. If the iPhone were a little smarter, it would only include the "space" key when the "multiple" attribute was present.

date/time input types

The new HTML5 date, datetime, datetime-local, month, week, and time input types are only supported by:

  1. Opera
  2. Chrome
  3. iOS Safari
  4. Blackberry Browser
  5. Chrome for Android

Browsers that support these input types present the user with contextually-appropriate dialogs such as date pickers. Here's the date input field on Chrome:

And here's the date input field on an iPhone:

number

The new HTML5 number input type is only supported by:

  1. Opera
  2. Chrome
  3. Safari

Supporting browsers present up and down buttons (spinboxes) to scroll through numbers and they also allow you to use the up and down arrows on the keyboard. Opera's spinbox is shown below: Opera Number Input Type

Safari on iPhone doesn't present spinboxes, but does offer the user the number-specific keypad:

All three implementations (Opera, Chrome and Safari) are subpar in that they don't accept decimals in their standard format. To see this:

  1. Open html5-forms/Demos/input-validity.html in Chrome, Opera, or Safari.
  2. In the number field, enter 3.3 or some other decimal.
  3. Press the Check Validity button. You'll receive an alert reading "3.3 is NOT a valid number." Oops.

range

The new HTML5 range input type is only supported by recent versions of all browsers.

Browsers currently represent range input types as sliders. This is nice, but the problem is that they don't indicate a value, so the user doesn't know what they've selected. Consider the following code:

Code Sample:

html5-forms/Demos/input-range.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
	<label for="pace">
		<strong>How is the pace of the class?</strong><br>
		<small>(1=way too slow, 9=way too fast, 5=perfect):</small>
	</label><br>
	<input type="range" name="pace" id="pace" min="1" max="9" value="5">
---- C O D E   O M I T T E D ----

The above code will render as follows (in Google Chrome):

The problem is that there is no indication of the current value. We can try fixing this with this simple little trick:

Code Sample:

html5-forms/Demos/input-range-title.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
	<label for="pace">
		<strong>How is the pace of the class?</strong><br>
		<small>(1=way too slow, 9=way too fast, 5=perfect):</small>
	</label><br>
	<input type="range" name="pace" id="pace" min="1" max="9" value="5"
		title="5" onchange="this.title=this.value">
---- C O D E   O M I T T E D ----

The above code will render as follows (in Safari):

This trick works pretty well in Safari, which displays the title value immediately after the mouse hovers over the field. However, with Chrome and Opera there is a slight delay, which makes this solution less than ideal. Also, the value is only visible when the cursor is over the field.

The output Element

There is a new HTML5 output element used to show output generated by a script on a page. For example, you could use it to show an error message or the result of a calculation based on values entered in form fields.

We can use the output element to create a better solution for making our range slider more user friendly:

Code Sample:

html5-forms/Demos/input-range-output.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
	<label for="pace">
		<strong>How is the pace of the class?</strong><br>
		<small>(1=way too slow, 9=way too fast, 5=perfect):</small>
	</label><br>
	<input type="range" name="pace" id="pace" min="1" max="9" value="5"
	onchange="document.getElementById('paceoutput').innerHTML=this.value;">
	<output for="pace" id="paceoutput">5</output>
---- C O D E   O M I T T E D ----

The above code will render as follows (in Safari): Notice the number 5 immediately after the slider telling us the current value of the slide. This number will update when the slider value changes. This solution works in browsers that support range. However, it creates a problem with non-supporting browsers. Here's how Internet Explorer 9 displays this page: Notice that 5 is repeated twice: once within the text field and once after it.

To fix this, we need to populate the output element dynamically if and only if the range input type is supported. Here's a possible solution:

Code Sample:

html5-forms/Demos/input-range-output-dynamic.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>HTML5 Form - Input Range Type</title>
<script src="../../html5-common/modernizr.min.js" type="text/javascript"></script>
<script>
	window.addEventListener("load", function() {
		if (Modernizr.inputtypes.range) {
			document.getElementById('paceoutput').innerHTML=document.getElementById('pace').value;	
			document.getElementById("pace").addEventListener("change", function() {
					document.getElementById('paceoutput').innerHTML=this.value;				
			}, false);	
		}
	}, false);
</script>
</head>
<body>
<form method="post" action="example.xyz">
	<label for="pace">
		<strong>How is the pace of the class?</strong><br>
		<small>(1=way too slow, 9=way too fast, 5=perfect):</small>
	</label><br>
	<input type="range" name="pace" id="pace" min="1" max="9" value="5">
	<output for="pace" id="paceoutput"></output>
</form>
</body>
</html>

This solves the problem. The code, which runs when the page is loaded:

  1. Sets the innerHTML of the output element to the value of the range input.
  2. Attaches an event listener to catch any changes of that value and update the output accordingly.
  3. And it only runs if the browser supports the range input type. We used Modernizr to check for that.

min, max, and step attributes

The min, max, and step attributes can be used on the number, range, and datepicker elements.

min and max are intuitive. They are used to set the minimum and maximum possible values.

The step attribute is used to indicate possible values in between the min and max values.

These attributes are only supported by:

  1. Opera
  2. Chrome
  3. Safari

Code Sample:

html5-forms/Demos/input-number-step.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
<label for="evennumber">Even Number: </label>
<input type="number" name="evennumber" id="evennumber" min="0" max="100" step="2">
---- C O D E   O M I T T E D ----

To see how this works:

  1. Open html5-forms/Demos/input-number-step.html in Chrome or Opera.
  2. Use the spinner to go up and down. Notice only even numbers are shown and that you cannot go below 0 or above 100.
  3. Type in 15 or some other odd number. Notice the field turns red.

Safari can validate the numbers based on min, max, and step, but doesn't provide an easy way to pick a number.

color

Only Opera and Chrome support the new HTML5 color input type, but, again, as browsers all fall back to type="text" when they don't recognize an input type, there is no harm in using the color input type now. When other browsers start implementing it, your visitors will likely get a nice color picker.

Safari recognizes valid color names and hexadecimal color formats, but doesn't provide an easy way to pick them. As we saw earlier with the number type, you can check the validity of the color input type with JavaScript. To see this:

  1. Open html5-forms/Demos/input-validity.html in Chrome or Safari.
  2. In the color field, enter "red" or "#ff0000".
  3. Press the Check Validity button. You'll receive an alert reading "red is a valid color."
  4. Now try it with a bad color name (e.g., "foo") and you'll get an alert reading "foo is NOT a valid color."

Opera's color picker is shown below: Opera Color Picker

If you click on Other... you get a large color picker with more options.

HTML5 New Form Attributes

HTML5 introduces two new attributes of the form element:

  1. autocomplete - "on" or "off". When set to "off" the browser should not use built-in features to help a user auto-fill the form.
  2. novalidate - Boolean. If included, the form should not validate on submission.

autocomplete

Browsers have different ways of choosing data to use for autocomplete. For example, Chrome does it based on previous form entries, while Opera uses its built-in contact list. Users can manage autocomplete in their browser's settings. When autocomplete is on, you see something like the behavior shown below in Firefox 4: Autocomplete in FF4 When autocomplete is off, that behavior is blocked.

You can set autocomplete on the form and/or on individual fields - setting, for instance, the form to have autocomplete="on" but a specific field to have autocomplete="off".

novalidate

The purpose of the novalidate attribute is to allow users to submit their forms even if the form data is invalid. For example, perhaps they're filling out an online application and you want to allow them to save the current state of their application even though some fields might not be valid.

Take a look at the following code.

Code Sample:

html5-forms/Demos/form-attributes.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
<form method="post" action="" autocomplete="on">
	<!--novalidate attribute not included-->
	<label for="fullname">Name: </label>
	<input type="text" name="fullname" id="fullname" required>
	<label for="email">Email: </label>
	<input type="email" name="email" id="email">
	<input type="submit">
</form>
---- C O D E   O M I T T E D ----

The screen shot below shows this page in Opera. Notice that the fullname field is required, but left empty, and the email field is of the email type, but is not a valid email. So, both fields are currently invalid. When submitting this form in Opera, you get the following results: If we were to include the novalidate attribute, the form would submit without erroring.

Some Other New Form Field Attributes

required

The required attribute is used to indicate that a form field must contain data. It is supported by recent versions of all browsers except Safari.

Code Sample:

html5-forms/Demos/required.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
	<label for="fullname">Name: </label>
	<input type="text" name="fullname" id="fullname" required>
---- C O D E   O M I T T E D ----

placeholder

The placeholder attribute is used to add placeholder text to the form field. It is only supported by recent versions of all browsers.

Code Sample:

html5-forms/Demos/placeholder.html
<!DOCTYPE HTML
---- C O D E   O M I T T E D ----
	<label for="fullname">Name: </label>
	<input type="text" name="fullname" id="fullname" placeholder="Enter Firstname">
	<input type="submit">
---- C O D E   O M I T T E D ----

Here's what it looks like in Firefox:

autofocus

The autofocus attribute can only go in one field on the page. It instructs the browser to place focus on that field allowing the user to begin typing as soon as the page loads.

Code Sample:

html5-forms/Demos/autofocus.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
	<label for="fullname">Name: </label>
	<input type="text" name="fullname" id="fullname" autofocus>
	<label for="email">Email: </label>
	<input type="email" name="email" id="email">
	<input type="submit">
---- C O D E   O M I T T E D ----

We used to accomplish this by adding onload="document.getElementById('fullname').focus();" to the <body> tag or some other similar scripting method. The HTML5 way is easier and comes with at least two added benefits:

  1. It works when scripting is turned off.
  2. Browser makers could potentially provide a preference setting for disabling autofocus.

HTML5 autofocus is supported in Internet Explorer from version 10 and modern version of all other browsers. Note that use of autofocus in earlier versions of Google Chrome led to some errors with form valiation and some other aspects of forms; the issue has since been fixed.

Autofocusing on a form element (the HTML5 way or through script) can cause problems for people using screen readers. For sighted people, it's generally okay if we provide one focus point for the keyboard (i.e., autofocus) and another one for the eyes (e.g., instructions for filling out the form), but for people using screen readers, there is only one focus point. So be careful not to skip over important contextual content when directing focus to the first form field.

autocomplete

The autocomplete attribute is used to override the browser's or form element's autocomplete behavior on a field by field basis. It is widely supported by HTML5-compliant browsers.

form

The form attribute is used to associate a form element with a form (by the form's id) in which it is not nested. This would typically be used for styling purposes; for example, if you wanted to have one or more form elements appear separately from the main form.

Note that the form attribute can be used with the label and fieldset elements as well as all the form fields (e.g., input, textarea, select,...). Unfortunately, only Opera supports it.

pattern

The pattern attribute is used to force a specific pattern (via a regular expression) within an form field. It is only supported by recent versions of all browsers except Safari.

Code Sample:

html5-forms/Demos/pattern.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
	<label for="telephone">Telephone: </label>
	<input type="tel" name="telephone" id="telephone" pattern="^\(?([2-9]\d\d)\)?[\-\. ]?([2-9]\d\d)[\-\. ]?(\d{4})$">
---- C O D E   O M I T T E D ----

Open this file in one of the supporting browsers and enter data in the field. It should remain red until the value is a valid 10-digit U.S.-style phone number. It will allow for parentheses around the area code and for dashes, spaces, and dots as separators.

New Form Elements

HTML5 introduces these new elements, which are often associated with forms:

  1. output
  2. datalist
  3. progress
  4. meter

We covered the output element earlier in this lesson.

The others are covered below.

datalist

The datalist element combined with the list attribute is used to provide a list of suggestions for an input field. It differs from the select element in that the associated input can accept values that are not included in the datalist. To use it, add a list attribute to an input, giving the attribute a value corresponding to the id of the datalist tag you want associated with the input; the datalist contains option tags denoting the values to suggest to the user. It is only supported by:

  1. Opera
  2. Firefox
  3. Chrome

Code Sample:

html5-forms/Demos/datalist.html
<!DOCTYPE HTML>
---- C O D E   O M I T T E D ----
<label for="color">Color: </label>
<input type="color" name="color" id="color" list="color-list">
<datalist id="color-list">
	<option value="#ff0000">
	<option value="#0000ff">
	<option value="#00ff00">
	<option value="#ffff00">
	<option value="#ffa500">
</datalist>
---- C O D E   O M I T T E D ----

Here's what it looks like in Firefox:

And here's what it looks like in Chrome; note that, because Chrome supports inputs of type color and because the datalist options are given as hex colors, the suggested values appear as a color picker:

progress and meter

HTML5 introduces the new progress and meter elements. They sometimes get confused, so we'll illustrate with an example.

We use both progress and meter in our HTML5 Cards application as shown below: Progress and Meter demo

The progress element is used to show the progress through some action. In this case, through completing the "deck" of flash cards. Another example would be a file download or completion of a form.

The meter element, according to the spec, "represents a scalar measurement within a known range". So the meter element is only used when you know the minimum and maximum values. We use it in the above HTML5 cards example to show the user's current score (between 0% and 100%). This is different from progress, which shows how much of the deck has been completed. The HTML markup for the two tags is shown below:

Progress: <progress id="amountComplete" max="100" value="0"><span>0</span>%</progress> Score: <meter id="score" max="100" value="0"><span>0</span>%</meter>

Only Chrome, Firefox, Safari, and Opera support the progress and meter tags, so we use the nested <span> tags in combination with JavaScript to provide similar functionality in other browsers. For example, here's what we show in IE9:Progress and Meter demo - IE9

The Form Element's change Event Handler

The progress and meter elements can be updated using the new change event handler on the form, rather than capturing changes on each individual form element:

document.getElementById('my-form').addEventListener("change",updateProgress,false);