ValidityState API: JavaScript Form Validation Made Simple

Learn how to leverage the native browser ValidityState interface for accessible, performant form validation without external libraries.

What is ValidityState?

The ValidityState interface represents the validity states that an HTML form element can be in with respect to constraint validation. Every form-associated element exposes a validity property that returns a ValidityState object containing read-only boolean properties indicating which specific validation constraints are being violated.

This granular approach means you can determine exactly why validation failed and respond accordingly--whether showing a specific error message, highlighting the problematic field, or preventing form submission entirely. For teams building professional web applications, leveraging native browser APIs like ValidityState delivers superior performance without external dependencies.

When you access an element's validity property, you receive an object with multiple properties that reflect different aspects of the element's validation state. The most important property is the valid property, which is true only when all validation constraints are satisfied. This interface is supported across all modern browsers and provides a reliable foundation for client-side form validation. Unlike custom validation solutions that require significant JavaScript code to check each constraint manually, ValidityState leverages the browser's native constraint validation machinery.

For performance-conscious applications, particularly those built on the Next.js framework, using native browser validation reduces JavaScript execution time and improves Core Web Vitals scores. The lightweight nature of native validation also supports accessibility requirements by ensuring fast, responsive interactions for all users.

MDN Web Docs on Constraint Validation

Key ValidityState Properties

Understanding each property enables precise validation handling

valid

True when all validation constraints pass. Your first check in any validation logic.

valueMissing

True when a required field contains no value. Indicates required attribute violation.

typeMismatch

True when value doesn't match email or URL format. Applies to type='email' and type='url' inputs.

patternMismatch

True when value fails pattern attribute regex. Enables complex format validation.

tooLong / tooShort

True when content exceeds maxlength or falls below minlength requirements.

rangeOverflow / rangeUnderflow

True when numeric/date values exceed max or fall below min boundaries.

Accessing ValidityState in JavaScript

Accessing an element's validity is straightforward--simply reference the validity property of any form-associated element. The returned object provides immediate access to all boolean properties without requiring additional processing. This direct access pattern makes ValidityState extremely efficient for validation logic.

Unlike approaches that require parsing error messages or implementing custom validation functions, the ValidityState API provides a direct, boolean answer to each validation question. For React and Next.js applications, this pattern integrates naturally with component state management--you can check validity in event handlers and update state accordingly without additional dependencies. When implementing comprehensive form solutions, this native approach reduces bundle size and maintenance overhead.

Accessing ValidityState Properties
1const emailInput = document.getElementById('customer-email');2const validityState = emailInput.validity;3 4console.log(validityState.valid); // true or false5console.log(validityState.valueMissing); // true if required and empty6console.log(validityState.typeMismatch); // true if format is invalid7 8// Practical validation function9function validateField(inputEl) {10 if (inputEl.validity.valid) {11 return { isValid: true, message: '' };12 }13 14 if (inputEl.validity.valueMissing) {15 return { isValid: false, message: 'This field is required.' };16 }17 18 if (inputEl.validity.typeMismatch) {19 return { isValid: false, message: 'Please enter a valid format.' };20 }21 22 return { isValid: false, message: inputEl.validationMessage };23}

Creating Custom Validation Messages

Custom validation messages help users understand exactly what went wrong and how to fix it. Browser defaults are often generic and unhelpful--custom messages provide context-specific guidance. The fundamental pattern involves checking the validity state and returning an appropriate message string based on which specific constraint failed.

For forms with multiple fields, organizing validation logic by field name provides better maintainability and allows field-specific messages. This pattern groups validation rules by field identifier, enabling each field to have unique message requirements while sharing the underlying ValidityState checking mechanism. This organizational approach becomes especially valuable when fields have different validation requirements, such as contact forms that include email validation alongside phone number formatting.

Cloud Four's guide on ValidityState provides additional patterns for field-specific validation logic.

Custom Validation Message Function
1function getValidationMessage(inputEl) {2 // Return empty string if field is valid3 if (inputEl.validity.valid) {4 return '';5 }6 7 // Check each validity property and return specific messages8 if (inputEl.validity.valueMissing) {9 return 'This field is required. Please enter a value.';10 }11 12 if (inputEl.validity.typeMismatch) {13 if (inputEl.type === 'email') {14 return 'Please enter a valid email address (e.g., [email protected]).';15 }16 if (inputEl.type === 'url') {17 return 'Please enter a valid URL (e.g., https://example.com).';18 }19 }20 21 if (inputEl.validity.patternMismatch) {22 return 'The format you entered is not valid. Please check the required format.';23 }24 25 if (inputEl.validity.tooShort) {26 return `This field requires at least ${inputEl.minLength} characters.`;27 }28 29 if (inputEl.validity.tooLong) {30 return `This field cannot exceed ${inputEl.maxLength} characters.`;31 }32 33 if (inputEl.validity.rangeUnderflow) {34 return `The minimum value is ${inputEl.min}.`;35 }36 37 if (inputEl.validity.rangeOverflow) {38 return `The maximum value is ${inputEl.max}.`;39 }40 41 // Fallback to browser's default message42 return inputEl.validationMessage;43}
Performance Benefits of ValidityState

Why native browser validation outperforms custom solutions

Native Performance

Validation runs in browser's optimized native code rather than interpreted JavaScript.

Smaller Bundle Size

No validation library dependencies means faster page loads and better Core Web Vitals.

Universal Support

Works in all modern browsers without polyfills. Consistent behavior across platforms.

Lower Maintenance

Browser-native code means no library updates or breaking changes to manage.

Accessibility Considerations

Accessible validation ensures all users, including those using screen readers, can understand and resolve validation errors. The ValidityState API enables creating messages that explain problems clearly, but additional HTML attributes are necessary to ensure these messages are properly associated with their fields and announced to assistive technologies. Implementing accessible forms is essential for inclusive web experiences.

Key Techniques

aria-describedby creates a programmatic association between form fields and their error messages. When this association exists, screen readers will announce the error message when focus moves to the field, ensuring visually hidden or off-screen messages remain accessible.

aria-invalid signals validation state to assistive technologies, allowing users to quickly identify which fields require attention:

if (inputEl.validity.valid) {
 inputEl.setAttribute('aria-invalid', 'false');
} else {
 inputEl.setAttribute('aria-invalid', 'true');
}

aria-live="polite" ensures error messages are announced without interrupting other announcements. For form submission errors that appear all at once, consider using "assertive" instead to ensure critical information is communicated immediately.

Best Practices for Modern Web Applications

Progressive Enhancement

Forms should function meaningfully even without JavaScript. Native HTML attributes like required, pattern, and type create validation that works without scripts. JavaScript enhancement layers custom messages and real-time feedback on this baseline. This progressive enhancement approach ensures that all users receive functional validation while those with JavaScript enabled enjoy an improved experience.

Writing Helpful Messages

Effective validation messages are:

  • Specific: Identify exactly which constraint failed and explain it in terms users understand
  • Constructive: Helpful tone, not punitive--users aren't trying to enter invalid data
  • Clear: Provide examples or explanations when the format requirements aren't obvious

Server-Side Validation

Client-side validation improves UX but never replaces server-side validation. Users can disable JavaScript or craft requests manually. Always validate on the server using similar logic to client-side checks. Effective web applications implement defense in depth, with server-side validation that mirrors client-side rules. For robust full-stack implementations, server-side validation ensures data integrity regardless of client capabilities.

MDN's constraint validation documentation emphasizes the importance of server-side validation as a necessary complement to client-side checks.

Frequently Asked Questions

Is ValidityState supported in all browsers?

Yes, ValidityState is supported in all modern browsers including Chrome, Firefox, Safari, and Edge. No polyfills are required for typical use cases.

Can I use ValidityState with React or Next.js?

Absolutely. Access validity via DOM refs in event handlers. The API works the same way in frameworks as in vanilla JavaScript, integrating naturally with component state management.

Does ValidityState work with custom validation?

For custom validation logic beyond HTML constraints, use setCustomValidity() to set the customError property on the validity state.

Should I use ValidityState or a validation library?

ValidityState is recommended for most use cases as it provides native performance and smaller bundle size. Libraries may offer convenience features but add overhead and maintenance.

Build Better Web Forms with Native Validation

Our team specializes in performant, accessible web applications using modern JavaScript frameworks and native browser APIs like ValidityState.

Sources

  1. MDN Web Docs - Constraint Validation - Official documentation on HTML5 constraint validation, covering basic constraints, validation attributes, and the Constraint Validation API methods.

  2. Cloud Four - Custom Validation Messages - Practical guide on the ValidityState API with code examples for custom validation messages, accessibility considerations, and progressive enhancement patterns.