Intro Into HTML5 Constraint Validation

Interactive websites and applications can’t be imagined without forms that enable us to connect with our users, and to obtain the data we need in order to secure smooth transactions with them. We do need valid user input, however we need to acquire it in a way that doesn’t frustrate our users too much.

While we can improve the usability of our forms with smartly chosen UX design patterns, HTML5 also has a native mechanism for constraint validation that allow us to catch input errors right in the front-end.

In this post, we’ll focus on browser-supplied constraint validation, and look into how frontend developers can secure valid user input using HTML5.

Why We Need Front-End Input Validation

Input validation has two main goals. The content we get needs to be:

1. Useful

We need usable data we can work with. We need to make people enter realistic data in the right format. For instance, no one who is alive today was born 200 years ago. Getting data like this may seem funny at first, but on the long term it’s annoying, and populates our database with useless data.

2. Secure

When referring to security, this means we need to prevent the injection of malicious content — whether deliberate or by accident.

Usefulness (getting reasonable data) can be achieved only on the client side, the backend team can’t help too much with this. To attain security, front- and backend developers need to work together.

If frontend developers properly validate input on the client side, the backend team will have to deal with much less vulnerabilities. Hacking (a site) often entails submitting extra data, or data in the wrong format. Developers can fight security holes like these, successfully fight from the front-end.

For instance, this PHP security guide recommends to check everything we can on the client side. They emphasize the importance of frontend input validation by giving many examples, such as:

"Input validation works best with extremely restricted values, e.g. when something must be an integer, or an alphanumeric string, or a HTTP URL."

In frontend input validation, our job is to impose reasonable constraints on user input. HTML5’s constraint validation feature provides us with the means to do so.

HTML5 Constraint Validation

Before HTML5, frontend developers were limited to validating user input with JavaScript, which was a tedious and error-prone process. To improve client-side form validation, HTML5 has introduced a constraint validation algorithm that runs in modern browsers, and checks the validity of the submitted input.

To make the evaluation, the algorithm uses the validation-related attributes of input elements, such as <input>, <textarea>, and <select>. If you want to know how constraint validation happens step by step in the browser check out this WhatWG doc.

Thanks to HTML5’s constraint validation feature, we can execute all standard input validation tasks on the client side without JavaScript, solely with HTML5.

To perform more complex validation-related tasks, HTML5 provides us with a Constraint Validation JavaScript API we can use to set up our custom validation scripts.

Validate with Semantic Input Types

HTML5 has introduced semantic input types that — apart from indicating the meaning of the element for user agents — can also be used to validate user input by limiting users to a certain input format.

Besides the input types that have already existed before HTML5 (text, password, submit, reset, radio, checkbox, button, hidden), we can also use the following semantic HTML5 input types: email, tel, url, number, time, date, datetime, datetime-local, month, week, range, search, color.

We can safely use HTML5 input types with older browsers, as they will behave as an <input type="text"> field in browsers that don’t support them.

Let’s see what happens when the user enters the wrong input type. Say we have created an email input field with the following code:

<form name="form" action="#" method="post">
	 <label for="youremail">Your Email:</label>
	 <input type="email" name="email" id="youremail">
	 <input type="submit" value="Submit">

When the user types a string that doesn’t use an email format, the constraint validation algorithm doesn’t submit the form, and returns an error message:

Email Validation

The same rule applies to other input types as well, for example for type="url" users can only submit an input that follows the URL format (starts with a protocol, such as http:// or ftp://).

Some input types use a design that doesn’t even allow users to enter a wrong input format, for example color and range.

<form name="form" action="#" method="post">
  <label for="bgcol">Background Color:</label>
  <input type="color" name="color" id="bgcol">
  <input type="submit" value="Submit">

If we use the color input type the user is constrained to either choosing a color from the color picker or staying with the default black. The input field is constrained by design, therefore it doesn’t leave much chance for user error.

Color Validation

When it’s appropriate, it’s worth considering using the <select> HTML tag which works similarly to these constrained-by-design input types; it lets users choose from a dropdown list.

<form name="form" action="#" method="post">
  <label for="favfruit">Your Favourite Fruit:</label>
  <select name="fruit" id="favfruit">
    <option value="apple">Apple</option>
    <option value="pear">Pear</option>
    <option value="orange">Orange</option>
    <option value="raspberry">Raspberry</option>
  <input type="submit" value="Submit">
Option Validation

Use HTML5’s Validation Attributes

Using semantic input types sets certain constraints on what users are allowed to submit, but in many cases we want to go a little bit further. This is when the validation-related attributes of the <input> tag can help us out.

Validation-related attributes belong to certain input types (they can’t be used on all types) on which they impose further constraints.

1. required for getting a valid input by all means

The required attribute is the most well-known HTML validation attribute. It’s a boolean attribute which means it doesn’t take any value, we just simply have to place it inside the <input> tag if we want to use it:

<input type="email" name="email" id="youremail" required>

If the user forgets to enter a value into a required input field, the browser returns an error message that warns them to fill in the field, and they can’t submit the form until they have provided a valid input. That’s why it’s important to always mark visually required fields to users.

The required attribute can be used together with the following input types: text, search, url, tel, email, password, date, datetime, datetime-local, month, week, time, number, checkbox, radio, file, plus with the <textarea>and <select> HTML tags.

2. min, max and step for number validation

The min, max and step attributes enable us to put constraints on number input fields. They can be used together with the range, number, date, month, week, datetime, datetime-local, and time input types.

The min and max attributes provide a great way to easily exclude unreasonable data. For instance the example below forces users to submit an age between 18 and 120.

<form name="form" action="#" method="post">
  <label for="yourage">Your Age:</label>
  <input type="number" name="age" id="yourage" min="18" max="120">
  <input type="submit" value="Submit">

When the constraint validation algorithm bumps into a user input smaller than the min, or larger than the max value, it prevents it from reaching the backend, and returns an error message.

Age with Min and Max Attributes

The step attribute specifies a numeric interval between the legal values of a numeric input field. For instance, if we want users to choose only from leap years we can add the step="4" attribute to the field. In the example below I used the number input type, as there’s no type="year" in HTML5.

<form name="form" action="#" method="post">
  <label for="yourleapyear">Your Favourite Leap Year:</label>
  <input type="number" name="leapyear" id="yourleapyear"
			min="1972" max="2016" step="4">
  <input type="submit" value="Submit">

With the pre-set constraints, users can only choose from leap years between 1972 and 2016 if they use the little up-arrow that comes with the number input type. They can also type a value manually into the input field, but in case it doesn’t meet the constraints, the browser will return an error message.

Step Validation
3. maxlength for text length validation

The maxlength attribute makes it possible to set a maximum character length for textual input fields. It can be used together with the text, search, url, tel, email and password input types, and with the <textarea> HTML tag.

The maxlength attribute can be an excellent solution for phone number fields that cannot have more than a certain number of characters, or for contact forms where we don’t want users to write more than a certain length.

The code snippet below shows an example for the latter, it constraints user messages to 500 characters.

<form name="form" action="#" method="post">
  <label for="yourmsg">Message (max 500 characters):</label>
  <textarea name="msg" id="yourmsg" cols="25" rows="4"
  <input type="submit" value="Submit">

The maxlength attribute doesn’t return an error message, but the browser simply doesn’t let users type more than the specified character number. That’s why it’s crucial to inform users about the constraint, otherwise they won’t understand why they can’t go on with the typing.

4. pattern for Regex validation

The pattern attribute allow us to use Regular Expressions in our input validation process. A regular expression is a pre-defined set of characters that form a certain pattern. We can use it either to search strings that follow the pattern, or to enforce a certain format defined by the pattern.

With the pattern attribute we can do the latter — constrain users to submit their input in a format that matches the given regular expression.

The pattern attribute has many use cases, but it can be especially useful when we want to validate a password field.

The example below requires users to enter a password that’s minimum 8 characters long, and contains at least one letter and one number (source of the regex I used).

<form name="form" action="#" method="post">
  <label for="yourpw">* Your Password:</label>
  <input type="password" name="pw" id="yourpw" required
  <input type="submit" value="Submit">

A few more things

In this article, we had a look at how to make use of the browser-supplied form validation provided by HTML5’s native constraint validation algorithm. For creating our custom validation scripts, we need to use the Constraint Validation API that can be the next step in refining form validation skills.

HTML5 forms are accessible by assistive technologies, so we don’t necessarily have to use the aria-required ARIA attribute to mark required input fields for screen readers. However it can still be useful to add accessibility support for older browsers. It’s also possible to opt out of constraint validation by adding the novalidate boolean attribute to the <form> element.