Validating web page forms is a remarkably difficult task. But if you make websites, you’d better be good at it.

Being good at it means not doing things like this:

That is godawful. It’s like vomit on a restaurant floor. Everyone wants to leave.

We’ve defined some principles for doing better:

  1. Invalid forms should repopulate with all data* that a user typed, so the user can see what they did wrong and easily correct mistakes.
  2. Error messages should be clearly worded, so the user understands both what the problem is and how to fix it.
  3. Input fields that fail to validate should be highlighted, so the user can quickly locate what needs to be corrected.
  4. Validation should be flexible where possible (phone number formats, for instance), to minimize errors and accomodate users’ different styles.

Pretty simple, right? Especially because these principles are mostly design-agnostic.

It’s NOT simple, though. Meeting each of these principles has a price. Let’s take a closer look:

Invalid forms should repopulate with all data* that a user typed, so the user can see what they did wrong and easily correct mistakes.

*With two exceptions: passwords and credit card numbers. These are not repopulated for security reasons.
Repopulating a form also gets tricky when dealing with form elements like checkboxes and select dropdowns. We have solid libraries of code to handle these, but it takes attention. Few things will frustrate a user more than filling in a form and having all the information they entered discarded or lost.

Another security concern is Cross-Site-Scripting (XSS). XSS attacks are made possible when user-supplied data is redisplayed on a page. Repopulating form data does exactly this. Methods of protection against XSS attacks are sanitizing (or filtering) user input, or escaping it upon redisplay.  It’s best to do both.

Error messages should be clearly worded, so the user understands both what the problem is and how to fix it.

Sometimes we think we’ve done a good job writing good error messages, and we find out from user testing that we’re wrong. Communication is hard.

Input fields that fail to validate should be highlighted, so the user can quickly locate what needs to be corrected.

This one is actually fairly easy. It’s also an area that touches design a bit — designers need to incorporate error states into their designs, or the user experience will feel disjointed.

Validation should be flexible where possible (phone number formats, for instance), to minimize errors and accomodate users’ different styles.

This one is a real tradeoff. We’re usually pretty strict about email addresses, but quite loose with phone numbers. It often depends on what’s being done with the data.

A final note on client-side validation: with the rise of robust javascript libraries, client-side form validation has become easier to do. We’ve tried it, and we haven’t liked the results. There are several drawbacks:

  • The biggest failing of client-side validation is that it just isn’t secure (unless the same validation is duplicated on the server). 
  • The second-biggest drawback is the way client-side validation smears logic across multiple layers. Messy and poor code is the result, often with code duplication or changes over time that cause the client validation to perform different checks then the server-side does.
  • And finally, client-side validation is tied to the specific architecture used for the in-browser experience. We can use our server-side validation with any javascript library, or with Flash-based forms. Doing client-side validation allows unwelcome dependencies to take root.

The advantage of client-side validation is speed. Toward that end, we’ve built a number of forms and components which use AJAX requests to submit form data, saving the browser from reloading and redisplaying the entire page. This gives dramatic speed gains, and will likely become more widespread.

Summary

You know how you’ll know if your form validation is really good? Because you won’t notice it. Noticing form validation (in the form of, “What the what?!”) means that the experience was broken in some way.