CSS :user-valid Pseudo-Class

The CSS :user-valid pseudo-class selects form controls that satisfy their validation constraints after the browser determines that sufficient user interaction has occurred. Unlike :valid, which can match controls immediately when a page loads, :user-valid allows positive validation styling to appear after the user interacts with a field. It is useful for providing feedback without marking untouched form controls as successfully completed.

:user-valid Syntax

:user-valid {
  property: value;
}

The pseudo-class matches a valid form control when the browser's user-interaction conditions are satisfied.

Basic Example

input:user-valid {
  border: 2px solid #228b22;
}

Applies a green border when an input matches :user-valid.

Multiple Form Controls

input:user-valid,
select:user-valid,
textarea:user-valid {
  border-color: #228b22;
}

Class Selector

.form-control:user-valid {
  background-color: #effbef;
}

No Arguments

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

How :user-valid Works

The browser evaluates HTML constraint validation rules to determine whether a form control is valid. The :user-valid pseudo-class adds an interaction condition so that valid-state styling is not necessarily displayed before the user has worked with the control.

Step 1 - Create a Required Input

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

Step 2 - Add Valid-State Styling

input:user-valid {
  border: 2px solid #228b22;
  background-color: #effbef;
}

Step 3 - Enter a Valid Value

Enter a username that satisfies the required and minimum-length constraints. The browser may apply the :user-valid state after the relevant user interaction.

Step 4 - Change the Value

If the value becomes invalid, the control stops matching :user-valid. It may match :user-invalid when the browser's interaction conditions are satisfied.

No JavaScript Required

Native HTML validation and CSS can provide basic valid-state feedback without JavaScript.

HTML Form Validation

The :user-valid pseudo-class uses the browser's built-in constraint validation system.

Required Fields

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

A required text field becomes valid when it contains a value that satisfies its constraints.

Email Addresses

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

The entered value must satisfy the browser's email address validation rules.

Minimum Length

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

The user-entered value must satisfy the applicable minimum-length constraint.

Number Ranges

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

The entered number must fall within the permitted range and satisfy any other applicable constraints.

Pattern Matching

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

A valid value must match the specified pattern.

Constraint Validation

The selector does not create validation rules. It styles controls that satisfy existing constraints after the browser's interaction condition is met.

User Interaction

The :user-valid pseudo-class helps delay positive validation feedback until it is appropriate to show.

Before Interaction

An optional empty input may match :valid immediately, but it generally does not match :user-valid before relevant interaction.

After Editing

Entering a valid value can cause the control to match :user-valid once the browser's interaction conditions are satisfied.

After Leaving a Field

Moving focus away from a field can affect when the browser applies user-valid styling.

After Form Submission

An attempted form submission can affect user-interaction validity states. The control must still be valid to match :user-valid.

Browser-Determined Timing

Browsers determine when sufficient interaction has occurred. Do not assume that all browsers apply :user-valid immediately after the first keystroke or focus change.

:valid vs. :user-valid

Both pseudo-classes select valid form controls, but their matching conditions differ.

Feature :valid :user-valid
Matches valid controlsYesYes
Requires user-interaction conditionsNoYes
Can match an untouched optional fieldYesGenerally no
Useful for delayed success stylingLess suitable by itselfYes

Using :valid

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

This may style an optional empty input as valid immediately.

Using :user-valid

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

This allows the browser to delay the positive styling until relevant user interaction occurs.

:user-valid vs. :user-invalid

These related pseudo-classes provide positive and negative validation feedback after user interaction.

Pseudo-Class Matches
:user-validValid controls when the user-interaction conditions are satisfied.
:user-invalidInvalid controls when the user-interaction conditions are satisfied.

Combined Example

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

Neutral Initial State

input {
  border: 2px solid #999;
}

A neutral border provides a consistent initial appearance before validation feedback becomes appropriate.

Changing Between States

As a user edits a control, the browser can update which validation pseudo-class matches. A control cannot be both valid and invalid at the same time.

Validation Attributes

HTML attributes establish the validation requirements that a control must satisfy before it can match :user-valid.

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.

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 every applicable constraint to be valid.

Disabled Controls

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

Form Submission

Valid form controls may receive positive styling after user interaction or an attempted submission, depending on browser behavior.

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-valid {
  border: 2px solid #228b22;
}

Successful Validation

When the entered email address satisfies the control's constraints and the interaction conditions are met, the field can match :user-valid.

Native Validation

The browser normally checks applicable constraints before allowing a form to submit.

The novalidate Attribute

The novalidate attribute disables interactive constraint validation during form submission. It does not remove the underlying validity states of individual controls.

Server-Side Validation

Client-side validation improves the user experience but does not replace server-side validation.

:user-valid Specificity

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

Specificity Examples

Selector Specificity
:user-valid0-1-0
input:user-valid0-1-1
.form-control:user-valid0-2-0
#email:user-valid1-1-0
:where(input:user-valid)0-0-0

Specificity Example

input {
  border: 2px solid #999;
}
input:user-valid {
  border-color: #228b22;
}

The second rule has higher specificity and changes the border color when the control matches :user-valid, assuming other cascade factors are equal.

Accessibility

Positive validation feedback should be understandable without relying entirely on color or visual appearance.

Do Not Rely on Color Alone

A green border alone may not clearly communicate successful validation to every user.

Use Visible Labels

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

Provide Clear 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>

Maintain Focus Indicators

Do not remove visible focus outlines when adding valid-state styling.

Screen Reader Feedback

The :user-valid pseudo-class changes styling but does not automatically announce a successful validation state to assistive technology.

Avoid Excessive Feedback

Use success indicators where they help users understand requirements rather than marking every optional field as successfully completed.

Best Practices

  • Use :user-valid to delay positive validation feedback until meaningful user interaction.
  • Define appropriate constraints with HTML attributes such as required, pattern, and minlength.
  • Keep untouched form controls visually neutral.
  • Use :user-invalid for corresponding error styling when appropriate.
  • Do not rely on color alone to communicate validation results.
  • Provide clear labels and instructions for required input formats.
  • Preserve keyboard focus indicators.
  • Test validation timing in multiple browsers.
  • Use server-side validation for submitted data.

:user-valid Example

This example uses a required email field. Enter a valid email address and leave the field to see the positive validation styling when the browser applies :user-valid. Enter an invalid address or submit an incomplete form to see the corresponding invalid state.

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-valid {
  border-color: #228b22;
  background-color: #effbef;
}
#validation-demo input:user-invalid {
  border-color: #c62828;
  background-color: #fff0f0;
}
#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 successful form submission from navigating away from the example. The browser handles the validation states.

Browser Result

Play in Editor

Note: The field receives a green border and light green background when it matches :user-valid. Invalid styling appears when it matches :user-invalid. The timing depends on browser validation behavior.

Browser Support

Baseline: Newly available. The :user-valid 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-valid 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