Skip to content

Latest commit

 

History

History
94 lines (65 loc) · 5.85 KB

draft.md

File metadata and controls

94 lines (65 loc) · 5.85 KB

Form validation in layers: From built-in browser validation to the Constraint Validation API

Layers

  1. Built-in browser validation
  2. Constraint Validation API (JavaScript)

What if you could use built-in browser validation and have a custom design in a progressively enhanced manner? You can! The Constraint Validation API provides a way to customize the design of the validation error UI/UX while leveraging browser built-in features for the validation of the form data. This article explores one example of how to progressively enhance the form validation experience with the Constraint Validation API.

First layer: Built-in browser validation

Browser built-in form validation features are able to validate most user data without relying on JavaScript. This provides the strong foundation required for building a progressively enhanced experience.

This can be accomplished by:

Base experience: Example

  • TODO Rename heading
  • TODO Video? GIF?
  • TODO Side-by-side comparison of :invalid vs :user-invalid

Image of browsers that don't support :user-invalid

One of the pushbacks against using browser built-in form validation is that :invalid styles are applied on page load before the user interacts with the form controls. No worries! This is where a progressive enhancement layer can be applied in browsers that support :user-invalid/:user-valid. Using :user-invalid/:user-valid instead of :invalid/:valid will only apply the styles after the user has interacted with the form control.

To support all browsers and apply :user-invalid/:user-valid in a progressively enhanced manner, the CSS could look something like this:

/* Use `:user-invalid`/`:user-valid` only if supported */
@supports selector(:user-invalid) {
  input:user-valid {
    /*  */
  }
  input:user-invalid {
    /*  */
  }
}
/** 
 * When not supported, fallback to `:invalid`/`:valid` 
 * Wrapping `:valid`/`:invalid` in a "not" `@supports` block ensures that the 
 * invalid styles are not applied on page load in browsers that do 
 * support `:user-invalid`/`:user-valid`
 */
@supports not selector(:user-invalid) {
  input:valid {
    /* styles */
  }
  input:invalid {
    /*  */
  }
}

Base experience: Pros

  • No JavaScript required
  • No need to write custom validation logic
  • Can handle the majority of validation use cases
  • The validation errors are automatically rendered and styled by the browser providing a consistent browser-specific experience
  • Validation error messages are localized automatically

Base experience: Cons

  • The validation error messages are not customizable
  • The :invalid styles are applied before the user has a chance to fill out the form field on browsers that do not support :user-invalid
  • Some form controls (e.g., a checkbox group) cannot be validated

Base experience: Summary

TODO Work on this

This is a fantastic example of how progressive enhancement can shine. All of these cons can be addressed with JavaScript. Progressive enhancement FTW!