Introduction
Filling out forms on the web has never been exactly fun, and it can be downright painful on a mobile device with its on-screen keyboard. But modern browsers help to make this much easier by providing new semantic input types and validation.
There is even more up to date forms guidance on our new Web Fundamentals site.
When used properly, these features make it significantly easier for users to provide the information needed, increasing completion rates, and improving accuracy.
One study found that simply providing inline validation increased the successful completion rate by 22% and decreased time to completion by 42%.
Browser support
Currently support for the new form and input elements is widespread on modern browsers, though there is often some difference in the way some pickers are displayed on desktop. Mobile browsers are relatively consistent in showing the right keyboard depending on the input type selected. For the most up to date information, check out the state of HTML5 Form Features on CanIUse.com or The Current State of HTML5 Forms from Wufoo.
New input types
HTML5 introduces a number of new input types. These new input types give hints to the browser about what type of keyboard layout to display for on-screen keyboards.
Many browsers provide built-in validation for some input types like email and url. On other elements, you can indicate a valid input format by providing a regular expression in the the pattern attribute. For more information, be sure to read the section on Validation.
Input Type | Description |
url |
For entering a URL. It must start with a valid URI scheme, (for example http://, ftp:// or mailto:). |
tel |
For entering phone numbers. It does not enforce a particular syntax for validation, so if you want to ensure a particular format, you can use pattern. |
email |
For entering email addresses. By default it will only take one, but if the multiple attribute is provided, a comma separated list of email addresses is valid. |
search |
A text input field styled in a way that is consistent with the platform's search field. |
number |
For numeric input, can be any rational integer or float value. |
color |
For choosing colors. |
range |
For number input, but unlike the number input type, the value is less important. It is displayed to the user as a slider control. |
datetime |
For entering a date and time value where the time zone is provided as GMT. |
datetime-local |
For entering a date and time value where the time zone provided is the local time zone. |
date |
For entering a date (only) with no time zone provided. |
time |
For entering a time (only) with no time zone provided. |
week |
For entering a date that consists of a week-year number and a week number, but no time zone. |
month |
For entering a date with a year and a month, but no time zone. |
Validation
Data validation doesn’t just help to keep your data clean, but it also helps improve the user experience. For example, datalists can provide auto-complete in text boxes suggesting options to the user. Warnings can be displayed when the users response doesn’t match the expected format. The JavaScript validation APIs can provide custom validation logic and prompt users with easy to understand error messages when they’ve provided invalid data.
Remember: Even with client side input validation, it is always important to validate data on the server to ensure consistency and security in your data.
Validation constraint attributes
The pattern attribute
The pattern attribute specifies a regular expression used to validate an input field. For the purpose of the example, let's say a part number consists of three uppercase letters followed by four digits. The use of pattern ensure that the field value matches the correct format for a part number.
<input type="text" id="partNumber" pattern="[A-Z]{3}[0-9]{4}" />
The required attribute
If the required attribute is present, then the field must contain a value before the form can be submitted. For example, to make the part number in the previous example required, we’d simply add the required attribute.
<input type="text" required id="partNumber" pattern="[A-Z]{3}[0-9]{4}" />
The min, max and step attributes
For numeric input types like number or range, you can specify the minimum and maximum values, as well as how much they should each increment/decrement when adjusted by the slider or spinners.
<input type="number" id="qty" min="0" max="100" step="1" />
You can also use the min and max attributes on any of the date type inputs.
The maxlength attribute
The maxlength attribute can be used to specify the maximum length of an input or textbox and is useful when you want to limit the length of information that the user can provide. For example, if you want to limit a filename to 12 characters, you can use the following.
<input type="text" id="83filename" maxlength="12" />
The novalidate attribute
In some cases, you may want to allow the user to submit the form even if it contains invalid input. To do this, add the novalidate attribute to the form element. In this case, all pseudo classes and JavaScript APIs will still allow you to check if the form validates.
<form role="form" novalidate>
<label for="inpEmail">Email address</label>
<input type="email" id="inpEmail" placeholder="Enter email">
</form>
Validation constraint APIs
The constraint validation API gives you powerful tools for handling custom validation. The API allows you to do things like set a custom error, check whether an element is valid, and determine the reason that an element is invalid. The table below lists the new JavaScript APIs and properties that are available on input elements.
API | Use |
willValidate |
Property that returns true or false if the element is a candidate for validation. |
validity |
Property that returns a ValidityState object
representing the validity states of the element.
|
validationMessage |
Property that returns a string with the reason the object failed the validation test. |
checkValidity() |
Returns true if the element satisfies all of it’s constraints, and false otherwise. |
setCustomValidity() |
Sets a custom validation message and the customError
property of the ValidityState object to true.
|
One good example of where you might use the JavaScript validation APIs
is to verify that the user has provided the correct email address on a
sign up form where they’re asked to enter it twice. For example, in the
blur
event for the second input, you would call the following
check function:
var elem = document.getElementById("email_addr_confirm");
elem.addEventListener("blur", verifyEmail);
function verifyEmail(input) {
input = input.srcElement;
if (input.value != document.getElementById('email_addr').value) {
// the provided value doesn’t match the primary email address
input.setCustomValidity('The two email addresses must match.');
} else {
// input is valid -- reset the error message
input.setCustomValidity('');
}
}
See the article on Constraint Validation for further details and additional uses.
The invalid event
In addition to the JavaScript APIs, the invalid event is fired when
checkValidity()
returns false, allowing you to provide
custom messages. For example you could set the innerText
of a
sibling element to the validationMessage
, providing users
with more information about why the input validation failed.
input.addEventListener("invalid", function(evt) {
var elem = evt.srcElement;
elem.nextSibling.innerText = elem.validationMessage;
});
Be careful when showing users the validationMessage
- it’s
often written in a way that makes sense to a developer but won’t make
sense to a non-technical user.
The datalist element
The datalist element isn't an input type, but a list of suggested input values to associated with a form field. It lets the browser suggest autocomplete options as the user types. Unlike select elements where users must scan long lists to find the value they’re looking for, and limiting them only to those lists, datalists provide hints as the user types.
<label for="inpChocType">Chocolates</label>
<input type="text" id="inpChocType" list="chocType">
<datalist id="chocType">
<option value="white" />
<option value="milk" />
<option value="dark" />
</datalist>
Remember: the datalist
values are
provided as suggestions, and users are not restricted to the suggestions
provided.
Other new form attributes
Several other common form features are provided by new attributes that would have previously required additional code.
The autocomplete attribute
There may be cases where you don’t want the browser to automatically fill
in data based on users past entries. You may want to use this in fields
like one-time passwords, pin numbers or password hints. In this case, you
can add the autocomplete="off"
to either the form element or
an individual element.
<input type="number" id="pinNum" min="0" max="9999" autocomplete="off" />
The autofocus attribute
On some forms, like the Google home page for example, you want the focus
to immediately jump to a specific input so that the user can quickly
begin using the form. While there are JavaScript helpers to do this,
they can sometimes be annoying when they move focus after you’ve already
started typing. Instead, you can use the autofocus
attribute
on an input element to specify that element as the primary form element.
<input type="text" id="partNum" pattern="[A-Z]{3}[0-9]{4}" autofocus />
The placeholder attribute
The placeholder
attribute provides a hint to the user about
what’s expected in the input by displaying its value as light text until
the element gets focus. The browser automatically handles blank values,
dirty inputs and other input states that would previously have to be
special cased in JavaScript.
<input type="text" id="partNum" pattern="[A-Z]{3}[0-9]{4}" placeholder="XXX9999"/>
Styling with CSS3
HTML5 also introduces a number of new pseudo-classes that can be used to style inputs based on their value or attributes, making it easier for users to understand if they’ve filled the form out properly before trying to submit it.
:valid
and:invalid
- explicitly sets the style for an element when the input is valid/invalid.:required
and:optional
- sets the style for elements that are required or optional.:in-range
and:out-of-range
- styling for elements that support the min and max attribute
The example below sets the outline of the box to be red when the user has provided invalid input, and to attract their attention, makes the text bold when the field has focus.
input:invalid {
outline: 2px solid red;
}
input:focus:invalid {
color: red;
}
Validation happens immediately as the user types, and it’s possible they’ll see the invalid style while typing. To prevent this, you can set the style to something else, like the example below.
input:not(:focus):invalid {
outline: 2px solid red;
}
input:focus:invalid {
outline: 2px solid blue;
}
Unfortunately this does mean that they won’t know the data entered is invalid until they move the focus away from that input.
New APIs for accessing field values
Beyond the constraint validation API, there are a few other new functions and properties that are helpful for input elements.
API | Use |
.stepUp() .stepDown() |
For numeric and date inputs, you can use the stepUp()
and stepDown() functions to adjust the value to its
next logical step.
|
.valueAsNumber |
Property that returns the value as a number, useful for numeric
inputs instead of having to do parseInt(element.value, 10)
or parseFloat(element.value, 10) .
|
.valueAsDate |
Property that returns the value as a Date object, useful for date inputs instead of having to manually parse them. |
The FormData Object
One of the enhancements to XMLHttpRequest
is the
introduction of the FormData
object. With the
FormData
object, you can create and send a set of key/value
pairs and, optionally, files using XMLHttpRequest
. When using
this technique, the data is sent in the same format as if you'd submitted
it via the form's submit()
method with the encoding type of
multipart/form-data.
FormData gives you a way to create HTML forms on-the-fly using JavaScript,
and then submit them using XMLHttpRequest.send()
.
Here's a simple example:
var formData = new FormData();
formData.append("part_num", "123ABC");
formData.append("part_price", 7.95);
formData.append("part_image", somefile)
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://some.url/");
xhr.send(formData);
You can also use FormData
to add additional data to an
existing form before submitting it.
var formElement = document.getElementById("someFormElement");
var formData = new FormData(formElement);
formData.append("part_description", "The best part ever!");
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://some.url/");
xhr.send(formData);
Putting it all together

Summary
With a trivial amount of additional work today, we can significantly reduce the amount of pain your users feel when filling out web forms. Simply using the appropriate input type and providing real time feedback about the data they’ve provided can make the difference between a completed transaction and a lost customer.