HTML5 required attributes are a fantastic addition to the HTML5 spec, they save a lot of time when working on client-side form validation and enhance the user’s experience. The HTML5 required attribute provides us with full client-side ‘required’ checking and validation, which is easy to add to several types of form elements.
Table of contents
The required attribute is developer friendly. It’s a boolean attribute too which means we don’t need to supply it any data, it’s either present or not. We can add it simply to form elements like so:
In browsers that support the attribute, you don’t need to do anything when it comes to alerting users they haven’t filled/checked in an input field (or textarea, radio buttons and so on…)
If someone were to not fill in/check a required input, the form would not submit the information and the user would be notified by a small popup above the relevant field that they needed to fill it in.
But what about legacy browsers?
I’m a big fan of writing as much code as I can, obviously when a project’s turnaround time is limited you’ll use any plugins/scripts at hand, but to really understand any polyfills/scripts - it’s great to read through the code and see what they’re actually doing. This will help you to understand the process, their capabilities and limitations.
In this tutorial, we are going to create a small feature detection for the HTML5 required attribute, and write a handy, markup agnostic (i.e. not limited to knowing your markup [classes and IDs etc.]) so you can take it away, build from or integrate as is. This will be a robust required attribute fallback that will allow us to do what the HTML5 required attribute does:
- Stop the form submitting if fields are left empty
- Add a custom notification message on any empty/unchecked fields
HTML5 feature detecting
When working with HTML5, it’s a good idea to feature detect on the client-side. A lot of people like using Modernizr (a feature detect library). I find it a little bloated for my needs as a quick Google search can find you any feature detect you need should you need to. I’ve been adding detects to a small library of my own which I keep, these are all handy one-liners that I reuse when needed. Let’s get going with the feature detect!
Adding the required attributes
This is easily done as you can see from the introduction, adding a required attribute to our markup is really simple (here I’ve created a quick form with some different input fields). The below fields include various input types: text, email, tel, url, radio, checkbox as well as the textarea element. Let’s add the required attributes where appropriate (we only need to add the required attribute once to radio and checkboxes with the same name attribute):
Required attribute loop
Now we’ve got a feature detect and a form full of required elements, we need to get working on the script. First of all, I’m going to loop through the elements with the required attributes, and run a feature detect inside it. This will let us extend the script at a later date in the future if we want to do anything else:
The next step is going to be swapping the required attributes (which will be unsupported by any browser reading the script) to swap them for classes. This will help when dealing with styling for older browsers as well as continuation of selectors throughout the script.
Let’s remove the attribute using jQuery’s removeAttr method, and add a class called ‘required’ - a nice straight swap. I’ve found it really manageable to append any required messaging initially, and simply setting them to display:none; form the get-go. This is good for a few reasons; there should be a lot less (if any) flickering if any required attributes need showing, and they aren’t appended when they’re needed - they’re already there on demand. It will help make our script a lot less bloated and easier to read later on too.
Attributes are all setup now for form submission, which of course will only fire if a required class exists, meaning we don’t need to do another feature check and can simply include a $(‘.required’) selector inside the form handler. Let’s look at how we can set that up. Our form has a class of ‘form’ for simplicity and is the only markup-reliant selector our script will need, the rest will automatically do its magic.
I’ve found using jQuery’s .on methods are much more flexible, you can easily include event delegation as well as chaining event listeners, which we’ll come onto later. Let’s progress with the next loop. As it stands, all of our required attributes are now classes, allowing us to target them on submit:
Checking empty values
Inside the loop, we need to think of the next step; checking empty values. Let’s start with the easiest - empty input fields. This can easily be done like so:
It’d be good to setup the loop now to incorporate this:
Nice and easy. So what do we need to do when the field is empty? Well, two things; first we need to stop the form submitting. Stopping the form submitting is fairly easy, we capture the submit event and prevent default, like so (see we’re passing e through the function and calling the preventDefault method on it):
Next we need to show the appended message:
The events will both fire together, doing exactly what we’d like it to. Next I’m going to fill in the else part to hide any errors:
Detecting if radio/checkboxes aren’t checked
Now we’ve checked if the values are empty (thankfully this covers input types text, email, tel, url and textareas), which makes the process fairly seamless. The next bit is a little trickier, radio and checkboxes. First we need to check self to see if it’s an input type radio or checkbox (self is a variable name I’ve created to use instead of $(this)):
Next we’ll be using the jQuery :not pseudo, which allows us to detect whether something is ‘not’ something else. Here’s how we’ll use it:
This will check if the element(s) are not checked for us. If you remember from earlier on, I mentioned that you need to apply the required attribute once to radios and checkboxes with the same name. This is because we can run a condition to say that at least one input with the same name has to be checked, otherwise the users selection will only be limited to the checkbox with the required attribute (we basically assign the required attribute once to a group, and any input in that group requires a selection) - or it won’t let them through. Here’s how we add that:
Translating to English, this says, if this isn’t checked, and (&&) the input with the same name hasn’t been checked, we can do something. Converting this to a shorthand if statement is best as we can add this easily to our empty input field check too. I’ll create a variable called checked and test against it:
|The above will fire if no input type radio or checkbox have been selected with the same name. We can save some code and test against empty input and radios/checkboxes at the same time using the or operator (||):|
While it’s looping our code will make the necessary condition checks.
Putting the full loop and submit handler together, we can paint a picture of how our script is looking, with comments to recap:
You’ll notice the penultimate line states ‘all other form submit handlers here’ - this is where you can carry on processing anything you need to post your data to the server, could be AJAX or other script validators you may need.
By default, the HTML5 required validator will only fire on form submission, I’m going to include an optional script that will notify the user that the field is required should they decide to leave the input field without filling anything in. This isn’t typical behaviour of the required attribute, but I think it really benefits front-end validation as it tells the user straight away they need to fill it in.
Coming back to what I mentioned earlier about chaining event listeners, we want to listen for a few different events now on this separate part of the script:
The blur event is fired when a user leaves an input field, so it may be worth informing them the field is required at this stage and no later. Also, radio inputs and checkbox inputs will fire a change event, so this script will intelligently cater for both. We’ll be reusing a few components from earlier to achieve this, so much will be familiar.
First, I’m going to listen on inputs and textareas, the only two elements we’re using above (it seems redundant to listen for individual input types and make our selectors complicated):
We want to tell jQuery that these inputs and textareas are the parent of our form, which is done by using a comma to separate the selectors:
And then run the event listening function:
We don’t need to create a new loop, as the jQuery library will power this automatically for us, so we can call upon the $(this) method again, with all the reused components:
The nice part about listening for blur/change events is that the check will fire, fire and fire. Which means if the user enters data, and then removes it - the script will know and show the relevant message. This has no interaction however with the form’s submission, it’s purely an additional add-on for validation on-the-fly before submission.
Putting everthing together, it looks as follows:
As the script runs according to the result of an initial feature detect, we can simply make the script run when the required attribute is supported, which it no doubt is if you’re reading this. Simply amend this line during the development stage of your project to test the fallback features:
Which drops the bang (!). This now says ‘if it supports the required attribute’ - do something. And there you have it.
Extra: Customising HTML5 popups