HTML Form Validation

Introduction to Form Validation

Form validation is the process of checking user input to ensure it meets specified criteria before submitting the data to the server. HTML5 introduced built-in form validation features that allow you to validate user input directly in the browser without JavaScript.

There are two main types of form validation:

  • Client-side validation: Happens in the browser before data is sent to the server
  • Server-side validation: Happens on the server after data is submitted
Important: Always implement server-side validation even when using client-side validation. Client-side validation improves user experience but can be bypassed, so it should never be the only form of validation.

HTML5 Built-in Validation

HTML5 provides several attributes for basic form validation:

Required Fields

The required attribute specifies that an input field must be filled out before submitting the form:

<input type="text" name="username" required>
Try submitting the form without filling this field

Min and Max Values

The min and max attributes specify the minimum and maximum values for numeric input types:

<input type="number" name="age" min="18" max="120">

Min and Max Length

The minlength and maxlength attributes specify the minimum and maximum number of characters allowed in a text field:

<input type="text" name="username" minlength="3" maxlength="15">

Pattern Matching

The pattern attribute specifies a regular expression that the input value must match:

<input type="text" name="zipcode" pattern="[0-9]{5}" title="Five digit zip code">
Try entering letters or fewer than 5 digits

Input Type Validation

Certain HTML5 input types have built-in validation:

Email Validation

The email input type validates that the input is a properly formatted email address:

<input type="email" name="email">
Try entering text without an @ symbol

URL Validation

The url input type validates that the input is a properly formatted URL:

<input type="url" name="website">
Try entering text without http:// or https://

Number Validation

The number input type validates that the input is a number and provides increment/decrement buttons:

<input type="number" name="quantity" min="1" max="10" step="1">

Validation Feedback

Browsers provide visual feedback for validation errors, but you can also use the CSS :valid and :invalid pseudo-classes to style valid and invalid inputs:

input:valid { border-color: green; } input:invalid { border-color: red; }

You can also use the :required, :optional, :in-range, and :out-of-range pseudo-classes for more specific styling.

Custom Validation Messages

The title attribute can be used to provide a custom validation message:

<input type="text" pattern="[A-Za-z]{3}" title="Three letter country code">
Try entering more or fewer than 3 letters

The Constraint Validation API

HTML5 also provides a JavaScript API for form validation, known as the Constraint Validation API. This API gives you more control over the validation process:

// Check if an input is valid const isValid = document.getElementById('email').validity.valid; // Get validation message const message = document.getElementById('email').validationMessage; // Check specific validity states const isTooShort = document.getElementById('username').validity.tooShort; const isPatternMismatch = document.getElementById('zipcode').validity.patternMismatch; // Set a custom validation message document.getElementById('password').setCustomValidity('Passwords must match'); // Clear a custom validation message document.getElementById('password').setCustomValidity('');

The validity property provides information about the validity of an input, including:

  • valueMissing: The element has a required attribute but no value
  • typeMismatch: The value is not of the correct type (e.g., email, url)
  • patternMismatch: The value doesn't match the specified pattern
  • tooLong: The value exceeds the maxlength attribute
  • tooShort: The value is shorter than the minlength attribute
  • rangeUnderflow: The value is less than the min attribute
  • rangeOverflow: The value is greater than the max attribute
  • stepMismatch: The value doesn't match the specified step
  • badInput: The browser can't convert the input to a valid value
  • customError: The element has a custom validation error message
  • valid: The element meets all validation constraints

Complete Form Validation Example

Here's a complete example of a form with various validation techniques:

<form id="registration-form" novalidate> <div> <label for="username">Username (3-15 characters):</label> <input type="text" id="username" name="username" minlength="3" maxlength="15" required> </div> <div> <label for="email">Email:</label> <input type="email" id="email" name="email" required> </div> <div> <label for="password">Password (min 8 characters):</label> <input type="password" id="password" name="password" minlength="8" required> </div> <div> <label for="confirm-password">Confirm Password:</label> <input type="password" id="confirm-password" name="confirm-password" required> </div> <div> <label for="age">Age (18-120):</label> <input type="number" id="age" name="age" min="18" max="120" required> </div> <div> <label for="phone">Phone (format: 123-456-7890):</label> <input type="tel" id="phone" name="phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" required> </div> <div> <label for="website">Website:</label> <input type="url" id="website" name="website"> </div> <div> <label for="zipcode">Zip Code (5 digits):</label> <input type="text" id="zipcode" name="zipcode" pattern="[0-9]{5}" title="Five digit zip code"> </div> <div> <label> <input type="checkbox" name="terms" required> I agree to the terms and conditions </label> </div> <button type="submit">Register</button> </form> <script> const form = document.getElementById('registration-form'); const password = document.getElementById('password'); const confirmPassword = document.getElementById('confirm-password'); // Custom validation for password matching function validatePassword() { if (password.value !== confirmPassword.value) { confirmPassword.setCustomValidity('Passwords do not match'); } else { confirmPassword.setCustomValidity(''); } } password.addEventListener('change', validatePassword); confirmPassword.addEventListener('keyup', validatePassword); form.addEventListener('submit', function(event) { if (!form.checkValidity()) { event.preventDefault(); // Show validation messages const inputs = form.querySelectorAll('input'); inputs.forEach(input => { if (!input.validity.valid) { // You could add custom error handling here console.log(input.name + ': ' + input.validationMessage); } }); } }); </script>

This example demonstrates:

  • Required fields
  • Length constraints
  • Type validation (email, url, number, tel)
  • Pattern validation
  • Range validation
  • Custom validation (password matching)
  • Form submission handling

Best Practices for Form Validation

  • Always implement both client-side and server-side validation
  • Use the appropriate input types for automatic validation
  • Provide clear, helpful error messages
  • Validate in real-time when possible (e.g., as the user types or when they leave a field)
  • Use the title attribute to provide hints about expected input format
  • Consider accessibility when implementing validation (screen readers should announce validation errors)
  • Test validation on different browsers and devices
  • Use the novalidate attribute on the form if you want to implement custom validation with JavaScript
  • Don't rely solely on HTML5 validation for complex validation rules
  • Consider using a validation library for complex forms