Accessible Client-side Form Validation with HTML5

Share on FacebookShare on LinkedInShare on Twitter

Connecting labels to inputs is easy! But what about required fields, error messages, and keyboard focus?

In this three part blog series we’ll learn to make accessible forms with HTML5, WAI-ARIA, and jQuery Validation. Our strategy will be to first try validation with HTML5 in the latest browsers that support these form attributes, then we will use WAI-ARIA which works with the latest screen readers, and finally for the folks who just can’t upgrade we’ll add the jQuery Validation plugin so even IE6 users can accessibly submit forms.

Demo Form with HTML5 Validation

Challenge Considered Meme Stick Figure Guy scratching chin

Basics

The basics of form accessibility are sometimes overlooked so I’ll point them out for review.

Every. Single. Field. Needs. A. Label.

Easy enough to remember? The only bulletproof way to ensure an accessible form field is to provide an explicitly connected label using the for and id attributes.

A quick test for an explicit label is to click on the label’s text with your mouse and if focus goes into the input then they are connected. This increases the click target size and really helps everyone click those tiny checkboxes and radio buttons.

Technique for WCAG 2.0 – Success Criteria 1.1.1 (Non-text Content), 1.3.1 (Info and Relationships), 3.3.2 (Labels or Instructions), and 4.1.2 (Name, Role, Value)

H44: Using label elements to associate text labels with form controls

HTML

<label for="fname">First Name *</label>

<input required type="text" name="fname" id="fname">

Output

Do this for every single field! If you don’t want to see the label then hide it off screen with CSS.

Radio Buttons & Checkboxes Need a Fieldset & Legend

HTML

<fieldset>

<legend>Gender *</legend>

  <input type="radio" name="gender" value="male" id="male">

  <label for="male">Male</label>

  <input type="radio" name="gender" value="female" id="female">

  <label for="female">Female</label>

</fieldset>

Output

Gender *

Technique for WCAG 2.0 – Success Criteria 1.3.1 (Info and Relationships) and 3.3.2 (Labels or Instructions)

H71: Providing a description for groups of form controls using fieldset and legend elements

Are All Instructions Spoken?

Are input formats spoken? Did you indicate the correct format for dates, phone numbers, etc.? Again, the best way to communicate form instructions to screen readers is to place them in the label.

HTML

<label for="bday">Birthday * MM/DD/YYYY</label>

<input type="text" name="bday" id="bday">

Output

Technique for WCAG 2.0 – Success Criteria 3.3.2 (Labels or Instructions) and 3.3.5 (Help)

G89: Providing expected data format and example

Required Fields

No one enjoys filling out forms! If you want to get useful data and not scare your users away then only require the least amount of fields as is necessary. Indicate the field is required by placing a red * in the label or the text (required).

Technique for WCAG 2.0 – Success Criterion 3.3.2 (Labels or Instructions)

H90: Indicating required form controls using label or legend

Error Messages

Example of a signup form with inline error messages placed to the right of the labels.

angry face rage guy memeHelp users out by providing useful error messages and suggestions to correct them. Placing the error in a label will cause a screen reader to speak each error as the user tabs through the form fields.

Keyboard Focus

One of the biggest failures with forms is not sending keyboard focus to the field with an error or the list of error messages. Assistive Technology users will have no idea there’s something wrong if the screen reader goes blank or their magnifier does not move focus to the error. When nothing happens after pressing the submit button they will assume your form is broken.

Techniques for WCAG 2.0 – Success Criteria 3.3.1 (Error Identification), 3.3.2 (Labels or Instructions), 3.3.3 (Error Suggestion), and 3.3.4 (Error Prevention (Legal, Financial, Data))

HTML5

Now that you’ve got the basics out of the way, adding HTML5 validation and usability enhancements is a piece of cake!

Required Attribute

With the HTML5 required attribute and HTML5 input types you can put the responsibility of accessible form validation on the browser developer.

HTML

<label for="lname">Last Name *</label>

<input type="text" name="lname" id="lname" required>



<input type="checkbox" name="tos" id="tos" required>

<label for="tos">* I agree to terms of service.</label>

Output

Screenshots of Different Input Types with the Required Attribute in Action on Mac OS X Lion
Browser Text Checkbox Radio
Chrome First Name * textbox focused Popover ! Please fill out this field. Checkbox focused * I agree to terms of service. Popover ! Please check this box if you want to proceed. Gender * fieldset legend Male radio button focused Popover ! Please select one of these options. Female radio button.
Firefox First Name * textbox red border focused Popover Please fill out this field. Checkbox focused red border * I agree to terms of service. Popover Please check this box if you want to proceed. Gender * fieldset legend Male radio button red border focused Popover Please select one of these options. Female radio button red border.

Of course the required attribute does not work on all browsers, Safari and Mobile Safari being the two where I miss support the most. You can read more about HTML5 browser support at The Current State of HTML5 Forms – The required Attribute by Chris Coyier (@chriscoyier) of CSS-Tricks fame. That resource is a bit out of date as support has improved in many browsers.

Input Types

DEVELOPERS Y U NO USE HTML5 INPUT TYPES?

HTML5 input types greatly enhance the usability and accessibility of forms on mobile devices. In iOS, the iPhone, iPad, & iPod Touch platform, most input types will display a keyboard enhanced for that data format. It is very rare to see forms in the wild take advantage of these simple usability enhancements. By default input type=text displays the normal alphabetic keyboard. If you need to type numbers, the @ symbol in an email address, or the .com for a URL extra taps are required.

Comparison of Input Types and Displayed Keyboard on the iPhone
Type type=text type=email type=tel
HTML
<label for="text">Text:</label>

<input type="text" name="text"

 id="text">
<label for="email">Email:</label>

<input type="email" name="email"

 id="email" />
<label for="tel">Tel:</label>

<input type="tel" name="tel"

 id="tel" />
Output
Screenshot Default keyboard displays alphabet characters with first letter capitalized by default. Email keyboard displays alphabet with additional @ and . symbol. Tel keyboard displays 10-digit numeric phone keypad with +, *, and # key.

input type=date on iPad & iPhone

HTML
<label for="date">Date:</label>

<input type="date" name="date" id="date" />
Output

Date type displays a date spinner popover on the iPad.Date spinner control replaces standard keyboard on iPhone.

Because these different keyboards and spinner controls are native to iOS they’re accessible by default. Apple’s done all the work for you.

Pattern Attribute

HTML
<label for="zip">Zip Code 5 Digits</label>

<input type="number" pattern="[0-9]*" maxlength="5" min="0" name="zip" id="zip">
 Output

iPhone Keyboard Comparison Screenshots

with Pattern Attribute

input type=number input type=number pattern=”[0-9]*”
The number type without a pattern attribute displays a keyboard with many small number and symbol buttons. The number type with a pattern attribute displays the 10-digit keypad with very large buttons similar to the tel keyboard.

Happy face rage guy with thumbs upjQuery Mobile shown on an iPhoneUsing the pattern attribute, pattern=”[0-9]*”, with the number input type will display the 10-digit numeric keypad similar to the tel keypad. This is much more usable than the standard number keyboard which shows a lot of keys that are not needed for simple numeric input like a Zip Code. We have fat fingers and mobile keyboards have tiny buttons. Anything you can do to increase the tap target size of a button really helps out!

HTML5Pattern.com has Regular Expression patterns that can be used to validate complex input types. These are live and can be tested in supported browsers.

You can visit HTML5 inputs and attribute support in a browser to test its support for HTML5 forms and click through all the input types. Another great page to test support for HTML5 form attributes is the jQuery Mobile – Text inputs Docs. I love the jQuery Mobile project as it does two things I’m passionate about, mobile & accessibility, very well!

Input Types Add More Stringent Validation

By adding an input type=email the browser will ask for more specific input formatting to make sure the user actually types an email address in the format name@domain.com.

Chrome screenshot Email * text field focused asdf Popover ! Please enter an email address.

If we add the required attribute to input type=number Firefox will ask for numeric data that matches the specified pattern attribute.

Firefox screenshot Zip Code text field focused asdfa Popover Please match the requested format.

Simple Mobile & Screen Magnification Usability & Accessibility Enhancements

Place Label Above Input

By placing the label directly above the input you improve the experience for mobile and screen magnification users. When focus is in the input the label will no longer be cut off like in the below example of the Gmail sign up form where the label is placed to the left but cut off when viewed on an iPhone.

iPhone screenshot of gmail signup form with labels placed to the left. Labels are cut off when input's have focus due to iOS zooming in when the keyboard displays.

Position Formatting Instructions Below Input with CSS

Using CSS you can enclose formatting instructions in a span tag and position them directly under the input so they are still visible when zoomed in.

HTML

<p class="instructions-container">

  <label for="zip">Zip Code <span class="instructions">5 Digits</span></label>

  <input type="number" pattern="[0-9]*" maxlength="5" min="0" name="zip" id="zip">

</p>

CSS

.instructions {

	position:relative;

	top: 1.6em;

	display:block;

}

.instructions-container {

	margin-bottom:2em;

}

.instructions-container label {

	margin-bottom:-1.2em;

}

Output

Hiding Labels Using CSS

You may want to visually hide some labels where the input might be obvious to most sighted users. We can use CSS positioning to do this. The code for this comes from the WebAIM article, CSS in Action: Invisible Content Just for Screen Reader Users.

HTML

<label for="areacode">Phone * <span class="hidden">Area Code</span></label>

<input required type="tel" name="areacode" id="areacode" maxlength="3">

-

<label for="threedigits" class="inline"> <span class="hidden">First Three Phone Digits</span> *</label>

<input required type="tel" name="threedigits" id="threedigits" maxlength="3">

-

<label for="fourdigits" class="inline"> <span class="hidden">Last Four Phone Digits</span> *</label>

<input required type="tel" name="fourdigits" id="fourdigits" maxlength="4">

CSS

.hidden

{position:absolute;

left:-10000px;

top:auto;

width:1px;

height:1px;

overflow:hidden;}

Output

You can disable CSS and the labels will become visible.

Demo Form with HTML5 Validation

Next Steps – Add WAI-ARIA

In the next blog post we’ll build off the work we did here and add ARIA form and validation enhancements that are only visible to screen readers.

Links to all three posts in this series:

  1. Accessible Client-side Form Validation with HTML5
  2. Accessible Client-side Form Validation with HTML5 & WAI-ARIA
  3. Accessible Client-side Form Validation with HTML5, WAI-ARIA, & the jQuery Validation Plugin

Comments? Questions?

Rage guy deep in thought scratching chinSo what do you think about HTML5 form validation? Is this a viable option with the limited browser support of the required attribute? Do we still have to rely on JavaScript validation or even server-side validation since a small percent of users disable JavaScript?

Let me know if you have any suggestions for improvement or find any mistakes. Leave a comment below or send me a message on Twitter @pauljadam.

 

Development Newsletter Sign-up Button

20 comments

  • web page Permalink

    What’s up, I would like to subscribe for this blog to get hottest updates, so where can i do it please assist.

  • Liz Permalink

    Agreed, demo linked does not work. I can submit it totally empty and receive no error messages.

  • George Permalink

    Hi Paul, great post!

    You can validate fields per group? For example: button submit1 validate input1 and input2 but button submit2 validate input3 and input4.

    thanks!

  • ideonexus Permalink

    Hello, Neat post. There is an issue together with your website in internet explorer, could test this? IE still is the marketplace chief and a big portion of people will pass over your excellent writing due to this problem.

  • emj Permalink

    Do you have a working demo? The demo form linked to does not work. Thanks!

  • HTML5 Accessibility | Clarissa Peterson Permalink

    […] Input types will also do some awesome things in desktop browsers – they will provide basic validation (checking if an email field entry is formatted like an email address, for example) and the browser won’t let you submit until you enter properly formatted information. The validation is both a regular visual error message in the browser, and a message provided in a screen reader. (Accessible Client-side Form Validation with HTML5) […]

  • ali Permalink

    hi,

    i am using some scripts freely available for my site – problem is the use syntax like:

    document.field.value

    – this works on their site but not in my firefox browser where i have to modify their code to:

    document.getElementById(“fieldid”).value

    this is too much work! how can i use the original code – why the original is not working in my browser??

    check out site: http://www.123-calc.com

    thanks.

  • Nisha Permalink

    Too good :)

  • Cocksy Permalink

    Hi there,

    Need some assistance about submitting a form on mobile. I have built the site for non-mobile devices AND mobile devices where people enter in selections and submit the selections to a “MAILTO:<got email addy in here". But when the person enters in their email address and selections (3 seperate fields) and then hits the "SUBMIT" button, it opens up the email client (gmail on iphone, Outlook on laptop etc) and creates it in an email that the user then has to send. I dont want that to happen, i just want it to email the form directly to the MAILTO address. Please help, and thanks :)

  • Paul J. Adam Permalink

    Hi shenbagakannan, it sounds like you want the checkboxes to be optional. I’m not sure if it’s possible with HTML5 to say that for example if there are 5 checkboxes then only at least one of them is required or two are required.

    I think it’s pretty much an all or nothing thing. Every checkbox marked required would have to be checked.

    It looks like it may be possible with the jQuery Validation plugin according to a post on Stack Overflow, Jquery Validation Plugin – Require 2 checkboxes.

  • shenbagakannan Permalink

    requied field will not work if multiple check box available in the form. For example, if I have 2 more checkbox and I want to select any one of the check box from there and I used required attribute in all check boxes. So it validate all the check boxes. But I want to check any one check box in this situation it will not work.

  • Paul J. Adam Permalink

    Hi AceoStar, good question. I looked at that zip code field which has type=”number” and maxlength=”5″ and that does not work in Chrome (Canary) or Safari on Mac. There are some similar questions on Stack Overflow about this. It actually does work fine in Firefox. Guess you just can’t have all browsers behave the way you want so the JavaScript fallback is needed. I’m sure as the browsers evolve they’ll all get on track to have good form constraints and HTML5 support.

    One solution that kind of works is to add max=”99999″ and if the user goes beyond this in Chrome Canary then focus is always sent back to that field but the error message bubble does not appear. Check out Chrome Canary, there even input type=”date” has a native date picker that works with the keyboard!

    A hacky way to limit it to 5 digits would be to change the input type to tel but that destroys the semantics.

    Thanks for reading!

  • AceoStar Permalink

    Chrome does not support maxlength & min for Number fields. In your example, you can enter a row of 9s. This is horribly inconvenient. Is there a work around that you know of? JS would be kinda hacky for what I’m doing and setting maxlength the html 4.01 way is no good either.

  • Paul J. Adam Permalink

    Hi Ravi, what browser are you using? If I use Safari which does not support HTML5 validation when I click submit it will submit the non functional form and blank out the contents (if there is any).

    If I use Chrome or Safari the HTML5 validation will stop the submit unless all required fields are filled. If they are filled it will submit it and then blank out the inputs. On a real world form this data would go to the sever. On these tests the form actually goes nowhere and just reloads on submit.

    Glad you liked the post!

  • Ravi Permalink

    Nice Post,Thanks

    I just have one issue not related to validation. But related to forms. Is there is simple way keep showing the Input values after the click, They disappear once you click the form.

  • Paul J. Adam Permalink

    Hi Sree, you’re right. Thanks for the catch! I changed my example’s input id attribute to id=”email2″ and the label to for=”email2″. Working correctly now.

  • Sree Permalink

    Interesting, on the ‘Leave a Reply’ form at the end of the article, I clicked on the label ‘Email (will not be published)(required)’ and it took me to a completely different email address field (which was part of an example in the article above.) I guess it goes without saying that one needs to be careful while choosing labels for form fields and has to make sure that there are no duplicates.

Leave a Reply

You can use these HTML tags:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>