CSS :user-invalid Pseudo-Class

The CSS :user-invalid pseudo-class selects form controls that fail constraint validation after the user has interacted with them sufficiently for the browser to display an invalid state. Unlike :invalid, which can match an empty required field immediately, :user-invalid helps avoid showing validation errors before the user has had an opportunity to enter information.

:user-invalid Syntax

:user-invalid {
  property: value;
}

The pseudo-class matches an invalid form control when the browser determines that the invalid state should be presented based on user interaction or an attempted form submission.

Basic Example

input:user-invalid {
  border: 2px solid #c62828;
}

Applies a red border to an input that matches :user-invalid.

Multiple Form Controls

input:user-invalid,
select:user-invalid,
textarea:user-invalid {
  border-color: #c62828;
}

Class Selector

.form-control:user-invalid {
  background-color: #fff0f0;
}

No Arguments

The pseudo-class is written as :user-invalid, without parentheses or arguments.

How :user-invalid Works

The browser uses HTML constraint validation to determine whether a form control is valid. The :user-invalid pseudo-class adds a user-interaction condition to that invalid state.

Step 1 - Create a Required Input

<label for="username">Username</label>
<input type="text" id="username" name="username" required>

Step 2 - Add Invalid-State Styling

input:user-invalid {
  border: 2px solid #c62828;
  background-color: #fff0f0;
}

Step 3 - Interact with the Input

When the user interacts with the field and leaves it invalid, the browser may apply the :user-invalid state. The exact timing is determined by the browser's validation behavior.

Step 4 - Correct the Value

Once the control satisfies its validation constraints, it no longer matches :user-invalid.

No JavaScript Required

Native HTML validation and CSS can provide basic invalid-state styling without JavaScript.

HTML Form Validation

The :user-invalid pseudo-class works with the browser's built-in constraint validation system.

Required Fields

<input type="text" name="name" required>

An empty required field is invalid.

Email Addresses

<input type="email" name="email" required>

An entered value that does not satisfy email address validation is invalid.

Minimum Length

<input type="text" name="username" minlength="4" required>

A value that fails an applicable minimum-length constraint is invalid. Length constraints have specific rules concerning user-entered values.

Number Ranges

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

Values outside the permitted range fail validation.

Pattern Matching

<input type="text" name="code" pattern="[A-Z]{3}" title="Enter three uppercase letters" required>

The entered value must satisfy the pattern when the pattern constraint applies.

Constraint Validation

The selector does not define validation rules. It styles controls that fail existing HTML validation constraints after the browser's user-interaction condition is satisfied.

User Interaction

The main purpose of :user-invalid is to avoid displaying invalid styling too early.

Before Interaction

An empty required input can match :invalid as soon as the page loads, but it generally does not match :user-invalid before relevant user interaction.

After Editing

When the user edits a control and leaves an invalid value, the browser can apply :user-invalid.

After Leaving a Field

Moving focus away from an invalid field can affect when the browser presents its invalid state.

After Form Submission

An attempted submission can cause invalid controls to match :user-invalid, even if those individual fields were not edited.

Browser-Determined Timing

The precise interaction conditions are determined by the browser. Do not assume that every browser applies the state immediately after the first keystroke or blur event.

:invalid vs. :user-invalid

Both pseudo-classes select invalid controls, but they differ in when they match.

Feature :invalid :user-invalid
Matches invalid controlsYesYes
Requires user-interaction conditionsNoYes
Can match an untouched required fieldYesGenerally no, until an interaction or submission condition is met
Useful for delayed error stylingLess suitable by itselfYes

Using :invalid

input:invalid {
  border-color: #c62828;
}

This can style an empty required field immediately.

Using :user-invalid

input:user-invalid {
  border-color: #c62828;
}

This delays the error styling until the browser considers the invalid state appropriate to show.

:user-valid vs. :user-invalid

The related :user-valid and :user-invalid pseudo-classes provide feedback about form validity after relevant user interaction.

Pseudo-Class Matches
:user-validA valid control when the browser's user-interaction conditions are satisfied.
:user-invalidAn invalid control when the browser's user-interaction conditions are satisfied.

Combined Example

input:user-valid {
  border-color: #228b22;
}
input:user-invalid {
  border-color: #c62828;
}

Valid controls can receive green borders, while invalid controls receive red borders after the relevant interaction conditions are met.

Neutral Initial State

input {
  border: 2px solid #999;
}

A neutral initial border avoids displaying success or error styling before the user begins working with the form.

Validation Attributes

HTML validation attributes determine whether a control satisfies its requirements. The :user-invalid pseudo-class can style controls that fail those requirements.

Attribute or Type Validation Purpose
requiredRequires a value or selection.
minlengthSets a minimum text length.
maxlengthSets a maximum text length.
patternRequires text to match a regular expression.
minSets a minimum permitted value.
maxSets a maximum permitted value.
stepRestricts permitted numeric or date increments.
type="email"Checks email address syntax.
type="url"Checks URL syntax.

Example with Multiple Constraints

<label for="account-name">Account Name</label>
<input type="text" id="account-name" name="account-name" minlength="4" maxlength="20" required>

The control must satisfy all applicable constraints to be valid.

Disabled Controls

Disabled form controls generally do not participate in constraint validation and do not match :user-invalid.

Form Submission

Attempting to submit a form can cause invalid controls to receive user-invalid styling, helping users identify fields that need attention.

HTML Example

<form action="/submit" method="post">
  <label for="email">Email</label>
  <input type="email" id="email" name="email" required>
  <button type="submit">Submit</button>
</form>

CSS Example

input:user-invalid {
  border: 2px solid #c62828;
}

Invalid Submission

If the user attempts to submit the form without a valid email address, the browser can apply :user-invalid to the field.

Native Validation

The browser normally prevents submission when a participating control fails constraint validation.

The novalidate Attribute

The novalidate attribute disables interactive constraint validation during form submission. It does not remove the controls' underlying validity states, but it changes the normal submission and validation behavior.

Server-Side Validation

Client-side validation does not replace server-side validation. Submitted data must still be validated by the server.

:user-invalid Specificity

The :user-invalid pseudo-class contributes a specificity of 0-1-0, like other standard pseudo-classes.

Specificity Examples

Selector Specificity
:user-invalid0-1-0
input:user-invalid0-1-1
.form-control:user-invalid0-2-0
#email:user-invalid1-1-0
:where(input:user-invalid)0-0-0

Specificity Example

input {
  border: 2px solid #999;
}
input:user-invalid {
  border-color: #c62828;
}

The second rule is more specific and changes the border color when the control matches :user-invalid, assuming other cascade factors are equal.

Accessibility

Validation feedback should be understandable to all users, including people who use keyboards and assistive technology.

Do Not Rely on Color Alone

A red border may be difficult to distinguish for some users. Provide descriptive error messages when validation fails.

Use Visible Labels

<label for="email-address">Email Address</label>
<input type="email" id="email-address" name="email" required>

Helpful Instructions

<label for="access-code">Access Code</label>
<input type="text" id="access-code" name="access-code" pattern="[0-9]{4}" aria-describedby="code-help" required>
<p id="code-help">Enter a four-digit code.</p>

Error Messages

When displaying a custom error message, associate it with the relevant control and explain how to correct the value.

Keyboard Navigation

Ensure that validation styling does not remove or obscure visible keyboard focus indicators.

ARIA Considerations

The :user-invalid pseudo-class changes CSS styling. It does not automatically add aria-invalid or custom error announcements.

Best Practices

  • Use :user-invalid to avoid displaying error styling before meaningful user interaction.
  • Define appropriate HTML validation constraints with attributes such as required, pattern, and min.
  • Provide visible labels and clear instructions for form controls.
  • Use descriptive error messages rather than relying on a red border alone.
  • Keep the initial appearance of untouched form controls neutral.
  • Use :user-valid when positive validation feedback is useful.
  • Preserve visible keyboard focus styles.
  • Test validation timing in different browsers.
  • Do not rely on client-side validation as a replacement for server-side validation.

:user-invalid Example

This example uses a required email field. The field begins with a neutral border. Enter an invalid email address and leave the field, or try to submit the form without completing it. The browser applies the invalid styling when the control matches :user-invalid.

HTML

<form id="validation-demo">
  <label for="demo-email">Email Address</label>
  <input type="email" id="demo-email" name="email" placeholder="name@example.com" required>
  <button type="submit">Check Email</button>
  <p id="form-status" role="status"></p>
</form>

CSS

#validation-demo label {
  display: block;
  margin-bottom: 6px;
}
#validation-demo input {
  display: block;
  width: 100%;
  max-width: 260px;
  box-sizing: border-box;
  padding: 8px;
  border: 2px solid #999;
  border-radius: 4px;
}
#validation-demo input:user-invalid {
  border-color: #c62828;
  background-color: #fff0f0;
}
#validation-demo input:user-valid {
  border-color: #228b22;
}
#validation-demo button {
  margin-top: 12px;
  padding: 8px 12px;
  cursor: pointer;
}

JavaScript

document.getElementById("validation-demo").addEventListener("submit", (event) => {
  event.preventDefault();
  document.getElementById("form-status").textContent = "Email is valid.";
});

The JavaScript prevents a valid form submission from navigating away from the demonstration. The browser handles the validation states.

Browser Result

Play in Editor

Note: The field receives a red border when it matches :user-invalid and a green border when it matches :user-valid. The timing of these states depends on browser validation behavior.

Browser Support

Baseline: Newly available. The :user-invalid pseudo-class is supported in current versions of major browsers, including Chrome, Edge, Firefox, and Safari. Older browser versions may not recognize the selector.

For current compatibility information, visit Can I Use? for :user-valid and :user-invalid support.

Specifications

The :user-invalid pseudo-class is defined in CSS Selectors Level 4 as a user-interaction pseudo-class for form validation.

Selectors Level 4 - User-Interaction Pseudo-Classes