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 controls | Yes | Yes |
| Requires user-interaction conditions | No | Yes |
| Can match an untouched required field | Yes | Generally no, until an interaction or submission condition is met |
| Useful for delayed error styling | Less suitable by itself | Yes |
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-valid | A valid control when the browser's user-interaction conditions are satisfied. |
:user-invalid | An 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 |
|---|---|
required | Requires a value or selection. |
minlength | Sets a minimum text length. |
maxlength | Sets a maximum text length. |
pattern | Requires text to match a regular expression. |
min | Sets a minimum permitted value. |
max | Sets a maximum permitted value. |
step | Restricts 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-invalid | 0-1-0 |
input:user-invalid | 0-1-1 |
.form-control:user-invalid | 0-2-0 |
#email:user-invalid | 1-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-invalidto avoid displaying error styling before meaningful user interaction. - Define appropriate HTML validation constraints with attributes such as
required,pattern, andmin. - 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-validwhen 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
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.
