The CSS :Invalid Pseudo-Class

Style form elements based on validation state using CSS. Learn how :invalid works, when to use it, and how to implement accessible form validation without JavaScript.

What is the :invalid Pseudo-Class?

The :invalid CSS pseudo-class is a powerful selector that targets form elements whose contents fail to validate according to their HTML5 constraint rules. Part of the CSS Selectors Level 4 specification, :invalid enables visual feedback on user input without requiring JavaScript, making it an essential tool for creating accessible, user-friendly forms.

This pseudo-class automatically evaluates whether form controls meet their defined constraints--including required attributes, pattern matching, type-specific validation, and numeric range limits--allowing developers to style invalid states purely through CSS.

As part of modern web development best practices, leveraging native browser validation reduces JavaScript dependencies while improving performance and accessibility.

How :invalid Works

HTML5 introduced native form validation through the constraint validation API. Elements become invalid when they don't meet their specified constraints. The :invalid pseudo-class simply allows you to target and style these elements.

Validation Constraints That Trigger :invalid

  • Required fields: Empty required inputs
  • Pattern mismatches: Values not matching the pattern attribute regex
  • Type validation: Email, URL, number format violations
  • Range limits: Values outside min/max bounds
  • Length violations: Values shorter/longer than minlength/maxlength
  • Value type errors: Non-numeric input in number fields

The browser automatically applies validity states based on these constraints, and CSS pseudo-classes like :invalid and :valid reflect this state without any JavaScript required. This native validation approach is a cornerstone of progressive enhancement strategies.

Basic Syntax and Usage

The :invalid pseudo-class follows standard CSS selector syntax and can be combined with other selectors for precise targeting. It works on individual elements, entire forms, or groups of elements.

/* Basic syntax */
:invalid {
 border-color: #dc3545;
}

/* Targeting specific input types */
input[type="email"]:invalid {
 background-color: #fff5f5;
}

/* Form-level validation */
form:invalid {
 outline: 2px solid #dc3545;
}

/* Chaining with other pseudo-classes */
input:focus:invalid {
 box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.25);
}

By combining :invalid with other selectors like :focus or type-specific selectors, you create precise validation styling that responds to user interaction patterns.

The :user-invalid Alternative

A common issue with :invalid is that it immediately shows errors on page load--even before users have interacted with the field. This creates a poor first impression for forms with empty required fields.

The :user-invalid pseudo-class solves this by only applying styles after the user has engaged with the element. This provides a much better user experience for initial form states.

Key Differences

Aspect:invalid:user-invalid
TimingImmediate on page loadOnly after user interaction
Initial StateShows errors immediatelyClean initial state
Use CaseReal-time validationGentle validation feedback
/* Better user experience with :user-invalid */
input:user-invalid {
 border-color: #dc3545;
 background-color: #fff5f5;
}

Live Form Demo: :invalid vs :user-invalid

Consider a registration form with three required fields: email, password confirmation, and phone number. Here's how the two pseudo-classes behave differently:

With :invalid:

  • Page loads → All empty required fields immediately show red borders
  • User hasn't typed anything yet, but form already looks "broken"
  • Creates cognitive load before user engagement begins

With :user-invalid:

  • Page loads → Clean form with no error indicators
  • User types in one field → Validation triggers for that specific field
  • User tabs away without completing → Error appears only then
  • Provides space for users to understand the form before judgment
<!-- Live demo structure -->
<form class="user-friendly-form">
 <input type="email" required placeholder="Enter email">
 <input type="tel" required placeholder="Phone number">
 <button type="submit">Register</button>
</form>

<style>
/* Aggressive validation */
.aggressive-form input:invalid {
 border-color: #dc3545;
}

/* User-friendly validation */
.user-friendly-form input:user-invalid {
 border-color: #dc3545;
}
</style>

Implementing :user-invalid is recommended for most forms, especially those with multiple required fields. It aligns with user-centered design principles by reducing initial friction and cognitive load.

Practical Examples

Email Validation

Email fields have specific validation requirements based on the HTML5 email type:

<form>
 <label for="email">Email Address:</label>
 <input 
 type="email" 
 id="email" 
 name="email" 
 required
 placeholder="[email protected]"
 >

 <label for="url">Website:</label>
 <input 
 type="url" 
 id="url" 
 name="url" 
 required
 placeholder="https://yourwebsite.com"
 >

 <button type="submit">Submit</button>
</form>

Pattern-Based Validation

Use the pattern attribute for custom validation using regular expressions:

<!-- US Zip Code -->
<input 
 type="text" 
 pattern="[0-9]{5}" 
 title="Five digit zip code"
 placeholder="12345"
>

<!-- Phone Number -->
<input 
 type="tel" 
 pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" 
 title="Format: 123-456-7890"
 placeholder="123-456-7890"
>

<!-- Password (at least 8 characters, 1 number) -->
<input 
 type="password" 
 pattern="^(?=.*[0-9])(?=.*[a-zA-Z]).{8,}$"
 title="Must contain at least 8 characters and 1 number"
>

These patterns can be combined with CSS validation styling to create intuitive form experiences that guide users toward correct input.

Form-Level Validation

Apply :invalid to entire forms to control submission behavior:

/* Disable submit button until form is valid */
form:invalid button[type="submit"] {
 opacity: 0.5;
 pointer-events: none;
 cursor: not-allowed;
}

/* Or show visual indicator on form */
form:invalid::before {
 content: "Please fix the errors below";
 display: block;
 color: #dc3545;
 margin-bottom: 1rem;
}

This approach is particularly useful for preventing premature form submission and reducing server-side validation load.

Accessibility Considerations

Critical: Color alone should not be the only indicator of invalid state. WCAG Success Criterion 1.4.1 requires that information not be conveyed through color alone, as users with color blindness may not perceive the visual cue.

Best Practices for Accessible Validation

  1. Combine color with icons or text
  2. Use ARIA attributes for screen reader support
  3. Provide descriptive error messages
  4. Manage focus appropriately
<!-- Accessible form with validation -->
<form>
 <div class="form-group">
 <label for="email">Email Address</label>
 <input 
 type="email" 
 id="email" 
 name="email" 
 required
 aria-invalid="true"
 aria-describedby="email-error"
 >
 <span id="email-error" class="error-message">
 Please enter a valid email address
 </span>
 </div>
</form>
/* Accessible invalid styling */
input[aria-invalid="true"] {
 border-color: #dc3545;
 background-image: url("data:image/svg+xml,...error-icon");
 background-repeat: no-repeat;
 background-position: right 10px center;
 padding-right: 35px; /* Space for icon */
}

.error-message {
 color: #dc3545;
 font-size: 0.875rem;
 display: block;
 margin-top: 0.25rem;
}

Accessible form validation is a key component of inclusive web design. By combining visual and auditory feedback, you ensure all users can successfully complete forms.

Best Practices for Form Validation

Use :user-invalid for Better UX

Prevents showing errors on page load, only highlighting issues after user interaction with each field.

Pair Visual and Text Feedback

Combine color changes with error messages and icons to ensure all users understand validation issues.

Test with Assistive Technologies

Verify forms work correctly with screen readers, keyboard navigation, and other assistive tools.

Provide Clear Error Messages

Error text should explain what went wrong and how to fix it, not just indicate that something is wrong.

Consider Real-Time Validation Timing

Balance between immediate feedback and waiting until users finish typing to avoid frustrating interruptions.

Progressive Enhancement

Ensure forms work without JavaScript, using CSS validation as a baseline with enhancements built on top.

Browser Compatibility

The :invalid pseudo-class has excellent browser support across all modern browsers. It is considered "Baseline" available, meaning it works reliably across:

  • Chrome (all versions)
  • Firefox (all versions)
  • Safari (all versions)
  • Edge (all versions)
  • Mobile browsers (iOS Safari, Chrome for Android)

Support has been consistent since July 2015, making :invalid a safe choice for production use without needing fallbacks for modern browsers.

Detection Approach

If you need to support very old browsers (which is rarely necessary today), you can use feature detection:

/* Feature detection for :invalid support */
@supports (selector(:invalid)) {
 /* Styles for browsers with :invalid support */
 input:invalid {
 border-color: #dc3545;
 }
}

@supports not (selector(:invalid)) {
 /* Fallback styles or JavaScript-based validation */
 .js .invalid-field {
 border-color: #dc3545;
 }
}

This broad compatibility makes CSS-based validation a reliable foundation for any web application.

Frequently Asked Questions

Conclusion

The :invalid pseudo-class is a fundamental tool for creating accessible, user-friendly forms in modern web development. By understanding how it works, when to use its :user-invalid variant, and how to combine visual styling with accessible error messaging, developers can create validation experiences that guide users effectively toward successful form submission.

Key takeaways:

  • Use :invalid for immediate validation feedback and form-level checks
  • Consider :user-invalid for better initial user experience on page load
  • Always pair visual indicators with accessible error messages for all users
  • Test across browsers and assistive technologies to ensure broad compatibility
  • Combine CSS validation with JavaScript for advanced validation scenarios

Implementing proper form validation enhances user experience, reduces form abandonment, and improves conversion rates for your web applications. Start using :invalid in your forms today to create more intuitive, accessible validation experiences.

Ready to Build Better Forms?

Our web development team specializes in creating accessible, user-friendly web applications with modern CSS techniques.

Sources

  1. MDN Web Docs - :invalid - The authoritative source for CSS pseudo-class documentation
  2. CSS-Tricks - :invalid - Practical developer resource with code examples
  3. ThatSoftwareDude - :user-valid and :user-invalid - Comparison of validation pseudo-classes
  4. W3C CSS Selectors Level 4 Specification - Official specification details
  5. WCAG 2.0 - Understanding Success Criterion 1.4.1 - Accessibility guidelines for color use