Data form validation

  • Revision slug: HTML/Forms/Data_form_validation
  • Revision title: Data form validation
  • Revision id: 342733
  • Created:
  • Creator: Sheppy
  • Is current revision? No
  • Comment

Revision Content

While you should always validate data on your servers, there are many benefits to additiona validation of data on the Web page itself. In many ways, users are annoyed by forms. By validating form data while the user is filling it out, the user can know immediately if they've made any mistakes; this saves the user the time of waiting on an HTTP response, and saves your server from dealing with bad form input. This article covers how to go about validating form data within your form's Web content.

Using browser-supplied form validation

One of the features of HTML5 is the ability to validate most user data without relying on scripts. This is done using validation attributes on form elements.

When an element is invalid

When an element is invalid, two things occur:

  • The element matches the {{cssxref(":invalid")}} CSS pseudo-class; this lets you apply a specific style to invalid elements. Similarly, valid elements match the {{cssxref(":valid")}} pseudo-class.
  • If the user tries to send the data, the browser will block the form and display an error message.

Validation constraints on {{HTMLElement("input")}} elements

All {{HTMLElement("input")}} elements can be validated using the {{htmlattrxref("pattern","input")}} attribute. This attribute expects a case sensitive Regular Expression as its value. If the element's value is not empty and doesn't match the regular expression specified by the {{htmlattrxref("pattern","input")}} attribute, the element is considered invalid.

A simple example

<form>
  <label for="choose">Would you prefer a banana or a cherry?</label>
  <input id="choose" name="i_like" pattern="banana|cherry">
  <button>Submit</button>
</form>
input:invalid {
  border: 1px solid red;
}

input:valid {
  border: 1px solid green;
}

{{EmbedLiveSample("A_simple_example", "100%", 50)}}

In this example, the {{HTMLElement("input")}} element accepts one of three possible values: the empty string, the string "banana" or the string "cherry".

The required attribute

If an element requires a value before the form should be submitted, you can mark the element using the {{htmlattrxref("required","input")}} attribute. When this attribute is true, the field is not allowed to be empty.

<form>
  <label for="choose">Would you prefer a banana or cherry?</label>
  <input id="choose" name="i_like" pattern="banana|cherry" required>
  <button>Submit</button>
</form>
input:invalid {
  border: 1px solid red;
}

input:valid {
  border: 1px solid green;
}

Notice how the field's border is different from the previous example.

{{EmbedLiveSample("The_required_attribute", "100%", 50)}}

Note: {{HTMLElement("input")}} elements with their {{htmlattrxref("type","input")}} attribute set to the value email or url do not need a {{htmlattrxref("pattern","input")}} attribute to be validated. Specifying the email type requires that the field's value be a well-formed email address (or a comma-separated list of email addresses if it has the {{htmlattrxref("multiple","input")}} attribute). Fields with the url type automatically requires a properly-formed URL.

Other validation constraints

All form elements that can receive user inputs ({{HTMLElement("textarea")}}, {{HTMLElement("select")}}, etc.) support the {{htmlattrxref("required","input")}} attribute, but it's worth noting that the {{HTMLElement("textarea")}} element does not support the {{htmlattrxref("pattern","input")}} attribute.

All text fields ({{HTMLElement("input")}} or {{HTMLElement("textarea")}}) can be constrained in size using the {{htmlattrxref("maxlength","input")}} attribute. A field is invalid if its value is longer than the {{htmlattrxref("maxlength","input")}} attribute's value. Most of the time, however, browsers don't let the user type a longer value than expected into text fields.

For the number fields, the {{htmlattrxref("min","input")}} and {{htmlattrxref("max","input")}} attributes also provide a validation constraint. If the field's value is lower than the {{htmlattrxref("min","input")}} attribute or higher than the {{htmlattrxref("max","input")}} attribute, the field will be invalid.

Here is a full example:

<form>
  <p>
    <fieldset>
      <legend>Title<abbr title="This field is mandatory">*</abbr></legend>
      <input type="radio" required name="title" id="r1" value="Mr" ><label for="r1">Mr. </label>
      <input type="radio" required name="title" id="r2" value="Ms"><label for="r2">Ms.</label>
    </fieldset>
  </p>
  <p>
    <label for="n1">How old are you?</label>
    <!-- The pattern attribute is not required on number field but 
         it can act as a fallback for browsers which don't implement 
         the number field but support the pattern attribute such as Firefox -->
    <input type="number" min="12" max="120" step="1" id="n1" name="age"
           pattern="\d">
  </p>
  <p>
    <label for="t1">What's your favorite fruit?<abbr title="This field is mandatory">*</abbr></label>
    <input type="text" id="t1" name="fruit" list="l1" required
           pattern="[Bb]anana|[Cc]herry|[Aa]pple|[Ss]trawberry|[Ll]emon|[Oo]range">
    <datalist id="l1">
        <option>Banana</option>
        <option>Cherry</option>
        <option>Apple</option>
        <option>Strawberry</option>
        <option>Lemon</option>
        <option>Orange</option>
    </datalist>
  </p>
  <p>
    <label for="t2">What's your e-mail?</label>
    <input type="email" id="t2" name="email">
  </p>
  <p>
    <label for="t3">Leave a short message</label>
    <textarea id="t3" name="msg" maxlength="140" rows="5"></textarea>
  </p>
  <p>
    <button>Submit</button>
  </p>
</form>
body {
  font: 1em sans-serif;
  padding: 0;
  margin : 0;
}

form {
  max-width: 200px;
  margin: 0;
  padding: 0 5px;
}

p > label {
  display: block;
}

input[type=text],
input[type=email],
input[type=number],
textarea,
fieldset {
/* required to properly style form 
   elements on WebKit based browsers */
  -webkit-appearance: none;
  
  width : 100%;
  border: 1px solid #333;
  margin: 0;
  
  font-family: inherit;
  font-size: 90%;
  
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

input:invalid {
  box-shadow: 0 0 5px 1px red;
}

input:focus:invalid {
  outline: none;
}

{{EmbedLiveSample("Other_validation_constraints", "100%", 420)}}

Customized error messages

As we saw in all our examples, each time the user try to send an invalid form, the bowsers display an error message. The way this message is displayed depends on each browser.

Those automated message have two drawbacks:

  • There is no standard way to change their look and feel through CSS.
  • They depend on the browser local, which means that you can have a page in a given language and the error message in another language.
French version of browsers on an English page
Browser Rendering
Firefox 17 (Windows 7) Example of an error message with Firefox in French on an English page
Chrome 22 (Windows 7) Example of an error message with Chrome in French on an English page
Opera 12.10 (Mac OSX) Example of an error message with Opera in French on an English page

To customize these two elements you cannot rely on CSS and HTML only; you have to use JavaScript.

HTML5 provides the constraint validation API to check and customize the state of a form element. Among the things possible, it's possible to change the text of the error message. Let's see a quick example:

<form>
  <label for="mail">I would like you to provide me an e-mail</label>
  <input type="email" id="mail" name="mail">
  <button>Try to send me</button>
</form>

In JavaScript, use the setCutomValidity method:

var email = document.getElementById("mail");

email.addEventListener("keyup", function (event) {
  if(email.validity.typeMismatch) {
    email.setCustomValidity("I expect an e-mail, darling!");
  } else {
    email.setCustomValidity("");
  }
});

{{EmbedLiveSample("Customized_error_messages", "100%", 50)}}

Validating forms using JavaScript

If you want to take control over the native error message look and feel, or if you want to deal with browsers that do not support HTML5 forms validation. There is no other way than using JavaScript.

The HTML5 constraint validation API

More and more browsers support this API and it becomes reliable. This API is a set of methods and properties available on each form element:

Properties
Property Description
validationMessage Returns the error message that would be shown to the user if the element was to be checked for validity.
validity It's an object containing a collection of validity states
validity.customError Returns true if the element has a custom error; false otherwise.
validity.patternMismatch Returns true if the element's value doesn't match the provided pattern; false otherwise.

If it returns true, the element will match the {{cssxref(":invalid")}} CSS pseudo-class.
validity.rangeOverflow Returns true if the element's value is higher than the provided maximum; false otherwise.

If it returns true, the element will match the {{cssxref(":invalid")}} and {{cssxref(":out-of-range")}} and CSS pseudo-class.
validity.rangeUnderflow Returns true if the element's value is lower than the provided minimum; false otherwise.

If it returns true, the element will match the {{cssxref(":invalid")}} and {{cssxref(":out-of-range")}} CSS pseudo-class.
validity.stepMismatch Returns true if the element's value doesn't fit the rules given by the step attribute; false otherwise.

If it returns true, the element will match the {{cssxref(":invalid")}} and {{cssxref(":out-of-range")}} CSS pseudo-class.
validity.tooLong Returns true if the element's value is longer than the provided maximum length; false otherwise.

If it returns true, the element will match the {{cssxref(":invalid")}} and {{cssxref(":out-of-range")}} CSS pseudo-class.
validity.typeMismatch Returns true if the element's value is not in the correct syntax; false otherwise.

If it returns true, the element will match the {{cssxref(":invalid")}} css pseudo-class.
validity.valid Returns true if the element's value has no validity problems; false otherwise.

If it returns true, the element will match the {{cssxref(":valid")}} css pseudo-class; the {{cssxref(":invalid")}} CSS pseudo-class otherwise.
validity.valueMissing Returns true if the element has no value but is a required field; false otherwise.

If it returns true, the element will match the {{cssxref(":invalid")}} CSS pseudo-class.
willValidate Returns true if the element will be validated when the form is submitted; false otherwise.
Methods
Method Description
checkValidity() Returns true if the element's value has no validity problems; false otherwise. Fires an invalid event at the element in the latter case.
setCustomValidity(message) Sets a custom error, so that the element would fail to validate. The given message is the message to be shown to the user when reporting the problem to the user.

If the argument is the empty string, it clears the custom error.

For legacy browsers, it's still possible to relay on polyfill such as H5F to compensate the lack of support (because we want to use a JavaScript API, in that case using a polyfill add no extra constraint to your application design)

Let's see how to use that API to build custom error messages:

<form novalidate>
  <p>
    <label for="mail">
      <span>I need an e-mail</span>
      <input type="email" id="mail" name="mail">
      <span class="error" aria-live="polite"></span>
    </label>
  <p>
  <button>try to send me</button>
</form>

This simple form uses the {{htmlattrxref("novalidate","form")}} attribute to turn off browser's automatic validation. It's required in order to take control over the validation. However, it does not disable the validation constrain API nor the application of the CSS pseudo-class {{cssxref(":valid")}}, {{cssxref(":invalid")}}, {{cssxref(":in-range")}} and {{cssxref(":out-of-range")}}. It means that even if the browser does not check the validity of the form before sending its data, you can still check it by yourself and style the form accordingly.

The aria-live attribute makes sure that our custom error message will be display to anyone, including assistive technologies.

/* This is just to make the example nicer */
body {
  font: 1em sans-serif;
  padding: 0;
  margin : 0;
}

form {
    max-width: 200px;
}

p * {
    display: block;
}

input[type=email]{
  -webkit-appearance: none;

  width: 100%;
  border: 1px solid #333;
  margin: 0;

  font-family: inherit;
  font-size: 90%;

  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

/* This is our style for the invalid fields */
input:invalid{
  border-color: #900;
  background-color: #FDD;
}

input:focus:invalid {
  outline: none;
}

/* This is the style of our error messages */
.error {
  width  : 100%;
  padding: 0;
 
  font-size: 80%;
  color: white;
  background-color: #900;
  border-radius: 0 0 5px 5px;
 
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.error.active {
  padding: 0.3em;
}
// There are many ways to pick a DOM node
var form  = document.getElementsByTagName('form')[0];
var email = document.getElementById('mail');
var error = document.querySelector('.error');
email.addEventListener("keyup", function (event) {
  // Each time the user types something, we check if the
  // email field is valid.
  if(email.validity.valid) {
    
    // In case there is an error message visible, if the field
    // is valid, we remove the error message.
    error.innerHTML = ""; // Reset the content of the message
    error.className = "error"; // Reset the visual state of the message
  }
}, false);
form.addEventListener("submit", function (event) {
  // Each time the user tries to send the data, we check
  // if the email field is valid.
  if(!email.validity.valid) {
    
    // If the field is not valid, we display a custom
    // error message.
    error.innerHTML = "I expect an e-mail, darling!";
    error.className = "error active";
    // And we prevent the form to be sent by canceling the event
    event.preventDefault();
  }
}, false);

Here is the live result:

{{EmbedLiveSample("The_HTML5_constraint_validation_API", "100%", 130)}}

The constraint validation API gives you a powerful tool to handle form validation. Especially, It allows you to deal with a highest precision on the User Interface (UI) than what is possible with HTML and CSS alone.

Validating forms without any build-in API

Sometimes, for example with legacy browsers or custom widgets, you will not be able (or will not want) to use the constraint validation API. In that case, you're still able to use JavaScript to validate your form. Validating a form is more a question of UI than real data validation tricks.

To validate a form, you have to ask yourself a few questions:

What kind of validation should I perform?
Basically you have to determine how to validate your data: String operation, Type conversion, RegExp, etc. It's up to you. Just remember that form data are always text and are accessed as string by JavaScript.
What happens if the form does not validate?
This is clearly a UI matter. You have to decide how the form will behave: Does the form send the data anyway? Should you highlight the fields in error? Should you display error messages? etc.
How to help the user to correct invalid data?
In order to reduce the user frustration it's very important to provide him with accurate information to correct an invalid form.

If you want to dig into forms validation UI requirements, you should read those resources:

In order to illustrate this, let's rebuild the previous example to have it working with a legacy browser:

<form>
  <p>
    <label for="mail">
        <span>I need an e-mail</span>
        <input type="text" class="mail" id="mail" name="mail">
        <span class="error" aria-live="polite"></span>
    </label>
  <p>
  <!-- Some legacy browsers need to have the `type` attribute
       explicitly set to `submit` on the `button`element -->
  <button type="submit">try to send me</button>
</form>

As you can see, the HTML is almost the same; we just remove what is HTML5 specific. Note that ARIA is an independent specification not specifically related to HTML5.

/* This is just to make the example nicer */
body {
  font: 1em sans-serif;
  padding: 0;
  margin : 0;
}

form {
  max-width: 200px;
}

p * {
  display: block;
}

input.mail {
  -webkit-appearance: none;

  width: 100%;
  border: 1px solid #333;
  margin: 0;

  font-family: inherit;
  font-size: 90%;

  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

/* This is our style for the invalid fields */
input.invalid{
  border-color: #900;
  background-color: #FDD;
}

input:focus.invalid {
  outline: none;
}

/* This is the style of our error messages */
.error {
  width  : 100%;
  padding: 0;
 
  font-size: 80%;
  color: white;
  background-color: #900;
  border-radius: 0 0 5px 5px;
 
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.error.active {
  padding: 0.3em;
}

The CSS also does not really change, we just turn the :invalid pseudo-class into a real class and we avoid using the attribute selector that does not work on Internet Explorer 6.

Now we can go to the JavaScript part:

// There are less ways to pick a DOM node with legacy browsers
var form  = document.getElementsByTagName('form')[0];
var email = document.getElementById('mail');

// The following is a trick to reach the next sibling Element node in the DOM
// This is dangerous because you can easily build an infinite loop.
// In modern browsers, you should prefer using element.nextElementSibling
var error = email;
while ((error = error.nextSibling).nodeType != 1);

// As per the HTML5 Specification
var emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;

// Many legacy browsers do not support the addEventListener method.
// Here is a simple way to handle this; it's fare from the only one.
function addEvent(element, event, callback) {
  var previousEventCallBack = element["on"+event];
  element["on"+event] = function (e) {
    var output = callback(e);
    
    // A callback that return `false` stop the callback chain
    // and interupt the execution of the event callback.
    if(output === false) return false;

    if(typeof previousEventCallBack === 'function') {
      output = previousEventCallBack(e);
      if(output === false) return false;
    }
  }
};

// Now we can rebuild our validation constraint
// Because we do not rely on CSS pseudo-class, we have to  
// set explicitly the valid/invalid class on our email field
addEvent(window, "load", function () {
  // Here, we test if the field is empty (remember, the field is not required)
  // If it is not, we check if its content is a well-formed e-mail address.
  var test = email.value.length === 0 || emailRegExp.test(email.value);
 
  email.className = test ? "valid" : "invalid";
});

// This defines what happens when the user type on the field
addEvent(email, "keyup", function () {
  var test = email.value.length === 0 || emailRegExp.test(email.value);
  if(test) {
    email.className = "valid";
    error.innerHTML = "";
    error.className = "error";
  } else {
    email.className = "invalid";
  }
});

// This defines what happens when the user try to submit the data
addEvent(form, "submit", function () {
  var test = email.value.length === 0 || emailRegExp.test(email.value);
 
  if(!test) {
    email.className = "invalid";
    error.innerHTML = "I expect an e-mail, darling!";
    error.className = "error active";

    // Some legacy browsers do not support the event.reventDefault() method
    return false;
  } else {
    email.className = "valid";
    error.innerHTML = "";
    error.className = "error";
  }
});

And the live result:

{{EmbedLiveSample("Validating_forms_without_any_build-in_API", "100%", 130)}}

So as you can see it's not that hard to build a validation system on our own. The difficult part is to make it generic enough to use it on any possible form cross browser. There is many libraries available to perform form validation, do not hesitate to use them, here's a few examples:

Remote validation

In some cases it can be useful to perform some remote validation. This kind of validation is necessary when the data are tied to the data stored on the server side of your application. One use case for this is registration forms when you ask for a user name. To avoid duplication it's smarter to perform an AJAX request to check the availability of the user name rather than asking the user to send the data and send him back the form with an error.

Performing such a validation requires taking a few precautions:

  • It requires exposing an API and some data publicly, be sure it is not sensitive data.
  • The network lag requires performing asynchronous validation. This require some UI work in order to be sure that the user will not be blocked if the validation is not performed properly.

Conclusion

Form validation does not require some complex JavaScript but it does require thinking carefully about the user. Always remember to help your user to correct the data he provides. To that end, be sure to:

  • Display explicit error messages
  • Be permissive about the input format
  • Point at exactly where the error occurs (especially on large forms)

Revision Source

<p>While you should always validate data on your servers, there are many benefits to additiona validation of data on the Web page itself. In many ways, <a href="http://www.slideshare.net/jwegesin/forms-suck" rel="external" title="http://www.slideshare.net/jwegesin/forms-suck">users are annoyed by forms</a>. By validating form data while the user is filling it out, the user can know immediately if they've made any mistakes; this saves the user the time of waiting on an HTTP response, and saves your server from dealing with bad form input. This article covers how to go about validating form data within your form's Web content.</p>
<h2 id="Using_browser-supplied_form_validation">Using browser-supplied form validation</h2>
<p>One of the features of <a href="/en-US/docs/HTML/HTML5" title="/en-US/docs/HTML/HTML5">HTML5</a> is the ability to validate most user data without relying on scripts. This is done using <a href="/en-US/docs/HTML/HTML5/Constraint_validation" title="/en-US/docs/HTML/HTML5/Constraint_validation">validation attributes</a> on form elements.</p>
<h3 id="When_an_element_is_invalid">When an element is invalid</h3>
<p>When an element is invalid, two things occur:</p>
<ul>
  <li>The element matches the {{cssxref(":invalid")}} CSS pseudo-class; this lets you apply a specific style to invalid elements. Similarly, valid elements match the {{cssxref(":valid")}} pseudo-class.</li>
  <li>If the user tries to send the data, the browser will block the form and display an error message.</li>
</ul>
<h3 id="Validation_constraints_on_.7B.7BHTMLElement(.22input.22).7D.7D_elements">Validation constraints on {{HTMLElement("input")}} elements</h3>
<p>All {{HTMLElement("input")}} elements can be validated using the {{htmlattrxref("pattern","input")}} attribute. This attribute expects a case sensitive <a href="/en-US/docs/JavaScript/Guide/Regular_Expressions" title="/en-US/docs/JavaScript/Guide/Regular_Expressions">Regular Expression</a> as its value. If the element's value is not empty and doesn't match the regular expression specified by the {{htmlattrxref("pattern","input")}} attribute, the element is considered invalid.</p>
<h4 id="A_simple_example">A simple example</h4>
<pre class="brush: html">
&lt;form&gt;
  &lt;label for="choose"&gt;Would you prefer a banana or a cherry?&lt;/label&gt;
  &lt;input id="choose" name="i_like" pattern="banana|cherry"&gt;
  &lt;button&gt;Submit&lt;/button&gt;
&lt;/form&gt;</pre>
<pre class="brush: css">
input:invalid {
  border: 1px solid red;
}

input:valid {
  border: 1px solid green;
}</pre>
<p>{{EmbedLiveSample("A_simple_example", "100%", 50)}}</p>
<p>In this example, the {{HTMLElement("input")}} element accepts one of three possible values: the empty string, the string "banana" or the string "cherry".</p>
<h4 id="The_required_attribute">The required attribute</h4>
<p>If an element requires a value before the form should be submitted, you can mark the element using the {{htmlattrxref("required","input")}} attribute. When this attribute is true, the field is not allowed to be empty.</p>
<pre class="brush: html">
&lt;form&gt;
  &lt;label for="choose"&gt;Would you prefer a banana or cherry?&lt;/label&gt;
  &lt;input id="choose" name="i_like" pattern="banana|cherry" required&gt;
  &lt;button&gt;Submit&lt;/button&gt;
&lt;/form&gt;</pre>
<pre class="brush: css">
input:invalid {
  border: 1px solid red;
}

input:valid {
  border: 1px solid green;
}</pre>
<p>Notice how the field's border is different from the previous example.</p>
<p>{{EmbedLiveSample("The_required_attribute", "100%", 50)}}</p>
<div class="note">
  <p><strong>Note:</strong> {{HTMLElement("input")}} elements with their {{htmlattrxref("type","input")}} attribute set to the value <code>email</code> or <code>url</code> do not need a {{htmlattrxref("pattern","input")}} attribute to be validated. Specifying the <code>email</code> type requires that the field's value be a well-formed email address (or a comma-separated list of email addresses if it has the {{htmlattrxref("multiple","input")}} attribute). Fields with the <code>url</code> type automatically requires a properly-formed URL.</p>
</div>
<h3 id="Other_validation_constraints">Other validation constraints</h3>
<p>All form elements that can receive user inputs ({{HTMLElement("textarea")}}, {{HTMLElement("select")}}, etc.) support the {{htmlattrxref("required","input")}} attribute, but it's worth noting that the {{HTMLElement("textarea")}} element does not support the {{htmlattrxref("pattern","input")}} attribute.</p>
<p>All text fields ({{HTMLElement("input")}} or {{HTMLElement("textarea")}}) can be constrained in size using the {{htmlattrxref("maxlength","input")}} attribute. A field is invalid if its value is longer than the {{htmlattrxref("maxlength","input")}} attribute's value. Most of the time, however, browsers don't let the user type a longer value than expected into text fields.</p>
<p>For the number fields, the {{htmlattrxref("min","input")}} and {{htmlattrxref("max","input")}} attributes also provide a validation constraint. If the field's value is lower than the {{htmlattrxref("min","input")}} attribute or higher than the {{htmlattrxref("max","input")}} attribute, the field will be invalid.</p>
<p>Here is a full example:</p>
<pre class="brush: html">
&lt;form&gt;
  &lt;p&gt;
    &lt;fieldset&gt;
      &lt;legend&gt;Title&lt;abbr title="This field is mandatory"&gt;*&lt;/abbr&gt;&lt;/legend&gt;
      &lt;input type="radio" required name="title" id="r1" value="Mr" &gt;&lt;label for="r1"&gt;Mr. &lt;/label&gt;
      &lt;input type="radio" required name="title" id="r2" value="Ms"&gt;&lt;label for="r2"&gt;Ms.&lt;/label&gt;
    &lt;/fieldset&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;label for="n1"&gt;How old are you?&lt;/label&gt;
    &lt;!-- The pattern attribute is not required on number field but 
         it can act as a fallback for browsers which don't implement 
         the number field but support the pattern attribute such as Firefox --&gt;
    &lt;input type="number" min="12" max="120" step="1" id="n1" name="age"
           pattern="\d"&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;label for="t1"&gt;What's your favorite fruit?&lt;abbr title="This field is mandatory"&gt;*&lt;/abbr&gt;&lt;/label&gt;
    &lt;input type="text" id="t1" name="fruit" list="l1" required
           pattern="[Bb]anana|[Cc]herry|[Aa]pple|[Ss]trawberry|[Ll]emon|[Oo]range"&gt;
    &lt;datalist id="l1"&gt;
        &lt;option&gt;Banana&lt;/option&gt;
        &lt;option&gt;Cherry&lt;/option&gt;
        &lt;option&gt;Apple&lt;/option&gt;
        &lt;option&gt;Strawberry&lt;/option&gt;
        &lt;option&gt;Lemon&lt;/option&gt;
        &lt;option&gt;Orange&lt;/option&gt;
    &lt;/datalist&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;label for="t2"&gt;What's your e-mail?&lt;/label&gt;
    &lt;input type="email" id="t2" name="email"&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;label for="t3"&gt;Leave a short message&lt;/label&gt;
    &lt;textarea id="t3" name="msg" maxlength="140" rows="5"&gt;&lt;/textarea&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &lt;button&gt;Submit&lt;/button&gt;
  &lt;/p&gt;
&lt;/form&gt;</pre>
<pre class="brush: css">
body {
  font: 1em sans-serif;
  padding: 0;
  margin : 0;
}

form {
  max-width: 200px;
  margin: 0;
  padding: 0 5px;
}

p &gt; label {
  display: block;
}

input[type=text],
input[type=email],
input[type=number],
textarea,
fieldset {
/* required to properly style form 
   elements on WebKit based browsers */
  -webkit-appearance: none;
  
  width : 100%;
  border: 1px solid #333;
  margin: 0;
  
  font-family: inherit;
  font-size: 90%;
  
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

input:invalid {
  box-shadow: 0 0 5px 1px red;
}

input:focus:invalid {
  outline: none;
}</pre>
<p>{{EmbedLiveSample("Other_validation_constraints", "100%", 420)}}</p>
<h3 id="Customized_error_messages">Customized error messages</h3>
<p>As we saw in all our examples, each time the user try to send an invalid form, the bowsers display an error message. The way this message is displayed depends on each browser.</p>
<p>Those automated message have two drawbacks:</p>
<ul>
  <li>There is no standard way to change their look and feel through CSS.</li>
  <li>They depend on the browser local, which means that you can have a page in a given language and the error message in another language.</li>
</ul>
<table>
  <caption>
    French version of browsers on an English page</caption>
  <thead>
    <tr>
      <th scope="col">Browser</th>
      <th scope="col">Rendering</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Firefox 17 (Windows 7)</td>
      <td><img alt="Example of an error message with Firefox in French on an English page" src="/files/4329/error-firefox-win7.png" style="width: 228px; height: 97px;" /></td>
    </tr>
    <tr>
      <td>Chrome 22 (Windows 7)</td>
      <td><img alt="Example of an error message with Chrome in French on an English page" src="/files/4327/error-chrome-win7.png" style="width: 261px; height: 96px;" /></td>
    </tr>
    <tr>
      <td>Opera 12.10 (Mac OSX)</td>
      <td><img alt="Example of an error message with Opera in French on an English page" src="/files/4331/error-opera-macos.png" style="width: 218px; height: 83px;" /></td>
    </tr>
  </tbody>
</table>
<p>To customize these two elements you cannot rely on CSS and HTML only; you have to use JavaScript.</p>
<p>HTML5 provides <a href="http://www.w3.org/TR/html5/forms.html#the-constraint-validation-api" rel="external" title="http://www.w3.org/TR/html5/forms.html#the-constraint-validation-api">the constraint validation API</a> to check and customize the state of a form element. Among the things possible, it's possible to change the text of the error message. Let's see a quick example:</p>
<pre class="brush: html">
&lt;form&gt;
  &lt;label for="mail"&gt;I would like you to provide me an e-mail&lt;/label&gt;
  &lt;input type="email" id="mail" name="mail"&gt;
  &lt;button&gt;Try to send me&lt;/button&gt;
&lt;/form&gt;</pre>
<p>In JavaScript, use the setCutomValidity method:</p>
<pre class="brush: js">
var email = document.getElementById("mail");

email.addEventListener("keyup", function (event) {
&nbsp; if(email.validity.typeMismatch) {
&nbsp;&nbsp;&nbsp; email.setCustomValidity("I expect an e-mail, darling!");
&nbsp; } else {
&nbsp;&nbsp;&nbsp; email.setCustomValidity("");
&nbsp; }
});</pre>
<p>{{EmbedLiveSample("Customized_error_messages", "100%", 50)}}</p>
<h2 id="Validating_forms_using_JavaScript">Validating forms using JavaScript</h2>
<p>If you want to take control over the native error message look and feel, or if you want to deal with browsers that do not support HTML5 forms validation. There is no other way than using JavaScript.</p>
<h3 id="The_HTML5_constraint_validation_API">The HTML5 constraint validation API</h3>
<p>More and more browsers support this API and it becomes reliable. This API is a set of methods and properties available on each form element:</p>
<table>
  <caption>
    Properties</caption>
  <thead>
    <tr>
      <th scope="col">Property</th>
      <th scope="col">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>validationMessage</code></td>
      <td>Returns the error message that would be shown to the user if the element was to be checked for validity.</td>
    </tr>
    <tr>
      <td><code>validity</code></td>
      <td>It's an object containing a collection of validity states</td>
    </tr>
    <tr>
      <td><code>validity.customError</code></td>
      <td>Returns <code>true</code> if the element has a custom error; <code>false</code> otherwise.</td>
    </tr>
    <tr>
      <td><code>validity.patternMismatch</code></td>
      <td>Returns <code>true</code> if the element's value doesn't match the provided pattern; <code>false</code> otherwise.<br />
        <br />
        If it returns <code>true</code>, the element will match the {{cssxref(":invalid")}} CSS pseudo-class.</td>
    </tr>
    <tr>
      <td><code>validity.rangeOverflow</code></td>
      <td>Returns <code>true</code> if the element's value is higher than the provided maximum; <code>false</code> otherwise.<br />
        <br />
        If it returns <code>true</code>, the element will match the {{cssxref(":invalid")}} and {{cssxref(":out-of-range")}} and CSS pseudo-class.</td>
    </tr>
    <tr>
      <td><code>validity.rangeUnderflow</code></td>
      <td>Returns <code>true</code> if the element's value is lower than the provided minimum; <code>false</code> otherwise.<br />
        <br />
        If it returns <code>true</code>, the element will match the {{cssxref(":invalid")}} and {{cssxref(":out-of-range")}} CSS pseudo-class.</td>
    </tr>
    <tr>
      <td><code>validity.stepMismatch</code></td>
      <td>Returns <code>true</code> if the element's value doesn't fit the rules given by the step attribute; <code>false</code> otherwise.<br />
        <br />
        If it returns <code>true</code>, the element will match the {{cssxref(":invalid")}} and {{cssxref(":out-of-range")}} CSS pseudo-class.</td>
    </tr>
    <tr>
      <td><code>validity.tooLong</code></td>
      <td>Returns <code>true</code> if the element's value is longer than the provided maximum length; false otherwise.<br />
        <br />
        If it returns <code>true</code>, the element will match the {{cssxref(":invalid")}} and {{cssxref(":out-of-range")}} CSS pseudo-class.</td>
    </tr>
    <tr>
      <td><code>validity.typeMismatch</code></td>
      <td>Returns true if the element's value is not in the correct syntax; false otherwise.<br />
        <br />
        If it returns <code>true</code>, the element will match the {{cssxref(":invalid")}} css pseudo-class.</td>
    </tr>
    <tr>
      <td><code>validity.valid</code></td>
      <td>Returns true if the element's value has no validity problems; false otherwise.<br />
        <br />
        If it returns <code>true</code>, the element will match the {{cssxref(":valid")}} css pseudo-class; the {{cssxref(":invalid")}} CSS pseudo-class otherwise.</td>
    </tr>
    <tr>
      <td><code>validity.valueMissing</code></td>
      <td>Returns true if the element has no value but is a required field; false otherwise.<br />
        <br />
        If it returns <code>true</code>, the element will match the {{cssxref(":invalid")}} CSS pseudo-class.</td>
    </tr>
    <tr>
      <td><code>willValidate</code></td>
      <td>Returns true if the element will be validated when the form is submitted; false otherwise.</td>
    </tr>
  </tbody>
</table>
<table>
  <caption>
    Methods</caption>
  <thead>
    <tr>
      <th scope="col">Method</th>
      <th scope="col">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>checkValidity()</code></td>
      <td>Returns true if the element's value has no validity problems; false otherwise. Fires an invalid event at the element in the latter case.</td>
    </tr>
    <tr>
      <td><code>setCustomValidity(<em>message</em>)</code></td>
      <td>Sets a custom error, so that the element would fail to validate. The given message is the message to be shown to the user when reporting the problem to the user.<br />
        <br />
        If the argument is the empty string, it clears the custom error.</td>
    </tr>
  </tbody>
</table>
<p>For legacy browsers, it's still possible to relay on <a href="https://github.com/ryanseddon/H5F" rel="external" title="https://github.com/ryanseddon/H5F">polyfill such as H5F</a> to compensate the lack of support (because we want to use a JavaScript API, in that case using a polyfill add no extra constraint to your application design)</p>
<p>Let's see how to use that API to build custom error messages:</p>
<pre class="brush: html">
&lt;form novalidate&gt;
  &lt;p&gt;
    &lt;label for="mail"&gt;
      &lt;span&gt;I need an e-mail&lt;/span&gt;
      &lt;input type="email" id="mail" name="mail"&gt;
      &lt;span class="error" aria-live="polite"&gt;&lt;/span&gt;
    &lt;/label&gt;
  &lt;p&gt;
  &lt;button&gt;try to send me&lt;/button&gt;
&lt;/form&gt;</pre>
<p>This simple form uses the {{htmlattrxref("novalidate","form")}} attribute to turn off browser's automatic validation. It's required in order to take control over the validation. However, it does not disable the validation constrain API nor the application of the CSS pseudo-class {{cssxref(":valid")}}, {{cssxref(":invalid")}}, {{cssxref(":in-range")}} and {{cssxref(":out-of-range")}}. It means that even if the browser does not check the validity of the form before sending its data, you can still check it by yourself and style the form accordingly.</p>
<p>The <a href="/en-US/docs/Accessibility/ARIA/ARIA_Live_Regions" title="/en-US/docs/Accessibility/ARIA/ARIA_Live_Regions">aria-live attribute</a> makes sure that our custom error message will be display to anyone, including assistive technologies.</p>
<pre class="brush: css">
/* This is just to make the example nicer */
body {
  font: 1em sans-serif;
  padding: 0;
  margin : 0;
}

form {
    max-width: 200px;
}

p * {
    display: block;
}

input[type=email]{
  -webkit-appearance: none;

  width: 100%;
  border: 1px solid #333;
  margin: 0;

  font-family: inherit;
  font-size: 90%;

  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

/* This is our style for the invalid fields */
input:invalid{
  border-color: #900;
  background-color: #FDD;
}

input:focus:invalid {
  outline: none;
}

/* This is the style of our error messages */
.error {
  width  : 100%;
  padding: 0;
 
  font-size: 80%;
  color: white;
  background-color: #900;
  border-radius: 0 0 5px 5px;
 
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.error.active {
  padding: 0.3em;
}</pre>
<pre class="brush: js">
// There are many ways to pick a DOM node
var form  = document.getElementsByTagName('form')[0];
var email = document.getElementById('mail');
var error = document.querySelector('.error');
email.addEventListener("keyup", function (event) {
  // Each time the user types something, we check if the
  // email field is valid.
  if(email.validity.valid) {
    
    // In case there is an error message visible, if the field
    // is valid, we remove the error message.
    error.innerHTML = ""; // Reset the content of the message
    error.className = "error"; // Reset the visual state of the message
  }
}, false);
form.addEventListener("submit", function (event) {
  // Each time the user tries to send the data, we check
  // if the email field is valid.
  if(!email.validity.valid) {
    
    // If the field is not valid, we display a custom
    // error message.
    error.innerHTML = "I expect an e-mail, darling!";
    error.className = "error active";
    // And we prevent the form to be sent by canceling the event
    event.preventDefault();
  }
}, false);</pre>
<p>Here is the live result:</p>
<p>{{EmbedLiveSample("The_HTML5_constraint_validation_API", "100%", 130)}}</p>
<p>The constraint validation API gives you a powerful tool to handle form validation. Especially, It allows you to deal with a highest precision on the User Interface (UI) than what is possible with HTML and CSS alone.</p>
<h3 id="Validating_forms_without_any_build-in_API">Validating forms without any build-in API</h3>
<p>Sometimes, for example with legacy browsers or <a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">custom widgets</a>, you will not be able (or will not want) to use the constraint validation API. In that case, you're still able to use JavaScript to validate your form. Validating a form is more a question of UI than real data validation tricks.</p>
<p>To validate a form, you have to ask yourself a few questions:</p>
<dl>
  <dt>
    What kind of validation should I perform?</dt>
  <dd>
    Basically you have to determine how to validate your data: String operation, Type conversion, RegExp, etc. It's up to you. Just remember that form data are always text and are accessed as string by JavaScript.</dd>
  <dt>
    What happens if the form does not validate?</dt>
  <dd>
    This is clearly a UI matter. You have to decide how the form will behave: Does the form send the data anyway? Should you highlight the fields in error? Should you display error messages? etc.</dd>
  <dt>
    How to help the user to correct invalid data?</dt>
  <dd>
    In order to reduce the user frustration it's very important to provide him with accurate information to correct an invalid form.
    <p>If you want to dig into forms validation UI requirements, you should read those resources:</p>
    <ul>
      <li>SmashingMagazine: <a href="http://uxdesign.smashingmagazine.com/2012/06/27/form-field-validation-errors-only-approach/" rel="external" title="http://uxdesign.smashingmagazine.com/2012/06/27/form-field-validation-errors-only-approach/">Form-Field Validation: The Errors-Only Approach</a></li>
      <li>SmashingMagazine: <a href="http://www.smashingmagazine.com/2009/07/07/web-form-validation-best-practices-and-tutorials/" rel="external" title="http://www.smashingmagazine.com/2009/07/07/web-form-validation-best-practices-and-tutorials/">Web Form Validation: Best Practices and Tutorials</a></li>
      <li>Six Revision: <a href="http://sixrevisions.com/user-interface/best-practices-for-hints-and-validation-in-web-forms/" rel="external" title="http://sixrevisions.com/user-interface/best-practices-for-hints-and-validation-in-web-forms/">Best Practices for Hints and Validation in Web Forms</a></li>
      <li>A List Apart: <a href="http://www.alistapart.com/articles/inline-validation-in-web-forms/" rel="external" title="http://www.alistapart.com/articles/inline-validation-in-web-forms/">Inline Validation in Web Forms</a></li>
    </ul>
  </dd>
</dl>
<p>In order to illustrate this, let's rebuild the previous example to have it working with a legacy browser:</p>
<pre class="brush: html">
&lt;form&gt;
  &lt;p&gt;
    &lt;label for="mail"&gt;
        &lt;span&gt;I need an e-mail&lt;/span&gt;
        &lt;input type="text" class="mail" id="mail" name="mail"&gt;
        &lt;span class="error" aria-live="polite"&gt;&lt;/span&gt;
    &lt;/label&gt;
  &lt;p&gt;
  &lt;!-- Some legacy browsers need to have the `type` attribute
       explicitly set to `submit` on the `button`element --&gt;
  &lt;button type="submit"&gt;try to send me&lt;/button&gt;
&lt;/form&gt;</pre>
<p>As you can see, the HTML is almost the same; we just remove what is HTML5 specific. Note that <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> is an independent specification not specifically related to HTML5.</p>
<pre class="brush: css">
/* This is just to make the example nicer */
body {
  font: 1em sans-serif;
  padding: 0;
  margin : 0;
}

form {
  max-width: 200px;
}

p * {
  display: block;
}

input.mail {
  -webkit-appearance: none;

  width: 100%;
  border: 1px solid #333;
  margin: 0;

  font-family: inherit;
  font-size: 90%;

  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

/* This is our style for the invalid fields */
input.invalid{
  border-color: #900;
  background-color: #FDD;
}

input:focus.invalid {
  outline: none;
}

/* This is the style of our error messages */
.error {
  width  : 100%;
  padding: 0;
 
  font-size: 80%;
  color: white;
  background-color: #900;
  border-radius: 0 0 5px 5px;
 
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.error.active {
  padding: 0.3em;
}</pre>
<p>The CSS also does not really change, we just turn the :invalid pseudo-class into a real class and we avoid using the attribute selector that does not work on Internet Explorer 6.</p>
<p>Now we can go to the JavaScript part:</p>
<pre class="brush: js">
// There are less ways to pick a DOM node with legacy browsers
var form  = document.getElementsByTagName('form')[0];
var email = document.getElementById('mail');

// The following is a trick to reach the next sibling Element node in the DOM
// This is dangerous because you can easily build an infinite loop.
// In modern browsers, you should prefer using element.nextElementSibling
var error = email;
while ((error = error.nextSibling).nodeType != 1);

// As per the HTML5 Specification
var emailRegExp = /^[a-zA-Z0-9.!#$%&amp;'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;

// Many legacy browsers do not support the addEventListener method.
// Here is a simple way to handle this; it's fare from the only one.
function addEvent(element, event, callback) {
  var previousEventCallBack = element["on"+event];
  element["on"+event] = function (e) {
    var output = callback(e);
    
    // A callback that return `false` stop the callback chain
    // and interupt the execution of the event callback.
    if(output === false) return false;

    if(typeof previousEventCallBack === 'function') {
      output = previousEventCallBack(e);
      if(output === false) return false;
    }
  }
};

// Now we can rebuild our validation constraint
// Because we do not rely on CSS pseudo-class, we have to  
// set explicitly the valid/invalid class on our email field
addEvent(window, "load", function () {
  // Here, we test if the field is empty (remember, the field is not required)
  // If it is not, we check if its content is a well-formed e-mail address.
  var test = email.value.length === 0 || emailRegExp.test(email.value);
 
  email.className = test ? "valid" : "invalid";
});

// This defines what happens when the user type on the field
addEvent(email, "keyup", function () {
  var test = email.value.length === 0 || emailRegExp.test(email.value);
  if(test) {
    email.className = "valid";
    error.innerHTML = "";
    error.className = "error";
  } else {
    email.className = "invalid";
  }
});

// This defines what happens when the user try to submit the data
addEvent(form, "submit", function () {
  var test = email.value.length === 0 || emailRegExp.test(email.value);
 
  if(!test) {
    email.className = "invalid";
    error.innerHTML = "I expect an e-mail, darling!";
    error.className = "error active";

    // Some legacy browsers do not support the event.reventDefault() method
    return false;
  } else {
    email.className = "valid";
    error.innerHTML = "";
    error.className = "error";
  }
});</pre>
<p>And the live result:</p>
<p>{{EmbedLiveSample("Validating_forms_without_any_build-in_API", "100%", 130)}}</p>
<p>So as you can see it's not that hard to build a validation system on our own. The difficult part is to make it generic enough to use it on any possible form cross browser. There is many libraries available to perform form validation, do not hesitate to use them, here's a few examples:</p>
<ul>
  <li>Standalone library
    <ul>
      <li><a href="/http://validatious.org" rel="external" title="/http://validatious.org">Validatious</a></li>
      <li><a href="http://rickharrison.github.com/validate.js/" rel="external" title="http://rickharrison.github.com/validate.js/">Validate.js</a></li>
    </ul>
  </li>
  <li>jQuery plug-in:
    <ul>
      <li><a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/" rel="external" title="http://bassistance.de/jquery-plugins/jquery-plugin-validation/">Validation</a></li>
      <li><a href="http://unwrongest.com/projects/valid8/" rel="external" title="http://unwrongest.com/projects/valid8/">Valid8</a></li>
      <li>etc.</li>
    </ul>
  </li>
</ul>
<h4 id="Remote_validation">Remote validation</h4>
<p>In some cases it can be useful to perform some remote validation. This kind of validation is necessary when the data are tied to the data stored on the server side of your application. One use case for this is registration forms when you ask for a user name. To avoid duplication it's smarter to perform an AJAX request to check the availability of the user name rather than asking the user to send the data and send him back the form with an error.</p>
<p>Performing such a validation requires taking a few precautions:</p>
<ul>
  <li>It requires exposing an API and some data publicly, be sure it is not sensitive data.</li>
  <li>The network lag requires performing asynchronous validation. This require some UI work in order to be sure that the user will not be blocked if the validation is not performed properly.</li>
</ul>
<h2 id="Conclusion">Conclusion</h2>
<p>Form validation does not require some complex JavaScript but it does require thinking carefully about the user. Always remember to help your user to correct the data he provides. To that end, be sure to:</p>
<ul>
  <li>Display explicit error messages</li>
  <li>Be permissive about the input format</li>
  <li>Point at exactly where the error occurs (especially on large forms)</li>
</ul>
Revert to this revision