Using HTML5 Form Validation
One of the great new features of HTML5 is the new collection of input field types (like date, email, etc.) Modern browsers have better widgets for the input types to make it easier to pick dates and to choose the correct keyboard in mobile (for example). But they can also be combined with the form validation API to validate the data input into forms.
Validating HTML5 Input Types
Modern browsers supporting the form validation API automatically validate that the data entered into an input matches the input type. For example, if you use:
the browser will validate that the text entered is an email address. If you use
an input
of type number, it will validate any that the content is a number and
validate any min, max, or step attributes that you set. It will also require
that you complete any input
s that have the required
attribute.
When you submit the form, the browser displays a nice little pop-up tooltip to let you know what errors you’ve made.
See the Pen HTML5 Form Validation 1 by Shaun Kelly (@6stringbeliever) on CodePen.
CSS
In addition to the pop-up messages, HTML5 form validation also gives you three
CSS pseudo classes you can use to style input elements: :valid
, :invalid
, and :required
. These pseudo classes update as you type. Here’s an example:
See the Pen HTML5 Form Validation 2 by Shaun Kelly (@6stringbeliever) on CodePen.
Custom Validation
Sometimes the built in validations don’t work for you. Perhaps you’re not okay with “b@jo” validating as a legit email address. Perhaps you need to validate something new like some annoying password requirements (must include six uppercase letters, two numbers, one special character, your middle name, your high school crush). Good news! Custom validation has you covered!
Just call setCustomValidity()
on the input element with whatever your desired
error message is to set the input as invalid. Call setCustomValidity()
with
no error message to return the input to a valid state.
See the Pen HTML5 Form Validation 3 by Shaun Kelly (@6stringbeliever) on CodePen.
Creating a Better User Experience
The default behaviors, while a nice freebie to progressively enhance upon, leave something to be desired from a user experience perspective.
- First of all, they don’t trigger until you attempt to submit the form.
- Second, the browser only displays a validation message for the first invalid field when you submit the form. If more than one field is invalid, you won’t find out until you fix the first one and try to submit again.
Ideally, you want to validate input fields as soon as the user starts typing. Of course, you don’t want to have one of those annoying forms that says your input is invalid before you’ve finished entering any data, so I think the best approach is to wait to validate a field until that field loses focus, then validate the fields as the user types.
Unfortunately, there’s no way to programmatically trigger the browser to display the validation message. So, you basically have to throw those built in tooltips out and then roll your own validation. Fortunately, we can use the rest of the web validation APIs to create and display our own validation messages in the manner we choose.
Short Circuiting Validation
The first thing we need to do is to tell the browser not to automatically
run validation checks on form submit. We do this using the novalidate
attribute
on the form:
We’re now responsible for asking the browser to validate fields and for displaying validation messages in whatever manner we choose.
Checking Validation
At any time you can check the validation state of the entire form or of a
single input
element using checkValidity()
, which simply returns a boolean
indicating if the element or form validates.
Getting and Displaying Validation Messages
If you want to display validation messages yourself, at any time, you can get the
validation message using the intput element’s validationMessage
property. This
property contains either the browser-default message for the input’s state or the
message set by setCustomValidity()
.
See the Pen HTML5 Form Validation 4 by Shaun Kelly (@6stringbeliever) on CodePen.
Blocking Form Submission
It’s pretty simple to block form validation until the form validates. You can call checkValidity()
on the form element rather than individual elements. This will only return true if all the elements in form are valid. Call this in an event listener for the form and set the disabled
attribute of the submit button based on the results:
See the Pen HTML5 Form Validation 5 by Shaun Kelly (@6stringbeliever) on CodePen.
Boo, Safari
HTML5 form validation has great support across modern browsers… except Safari. Safari supports the API, but it doesn’t prevent invalid forms from being submitted and it doesn’t display the nice little popups like Chrome and Firefox.
The other big downer with Safari is that the validation messages
are not at all user friendly. For example, if you don’t complete a
required field, the validation message in Chrome and Firefox is “Please
fill out this field.” In Safari, it’s “value missing”. For a bad email
address, Safari just says “type mismatch”. So, you can’t count on an
HTMLInputElement’s validationMessage property in Safari unless you set
it yourself using setCustomValidation()
.
Feature Detection
Feature detecting the form validation API is simple:
If you use Modernizr, use:
Muchas Gracias
Credit for most of what I have learned about web form validation goes to Cameron Pittman and Ido Green’s Udacity course on web forms, MDN’s Data Validation API reference, and a bunch of practice working through the Senior Web Developer nanodegree at Udacity.