CSS :valid Pseudo-Class

The CSS :valid pseudo-class selects form controls whose values satisfy their HTML validation constraints. It can style inputs, selects, and other form elements that pass validation, providing visual feedback as users complete a form. Unlike :user-valid, the :valid pseudo-class does not require prior user interaction and can match a control as soon as the page loads.

:valid Syntax

:valid {
  property: value;
}

The :valid pseudo-class matches a form control when its value satisfies all applicable validation constraints.

Basic Example

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

Applies a green border to inputs that pass validation.

Multiple Form Controls

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

Required Valid Inputs

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

Limits the styling to required inputs that currently pass validation.

Class Selector

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

No Arguments

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

How :valid Works

The browser evaluates HTML constraint validation rules. When a control satisfies all applicable constraints, it matches :valid. If it fails a constraint, it may match :invalid instead.

Step 1 - Create a Required Input

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

Step 2 - Add Validation Styling

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

Step 3 - Enter a Valid Value

Enter a username that satisfies the required and minimum-length constraints. The input matches :valid when all applicable constraints are satisfied.

Step 4 - Enter an Invalid Value

Remove the required value or enter a user-provided value that violates an applicable constraint. The input stops matching :valid and matches :invalid.

Automatic Updates

The browser updates validation pseudo-class matching as the control's validity changes. No JavaScript is required for basic styling.

HTML Constraint Validation

HTML constraint validation determines whether form controls satisfy requirements such as required values, permitted ranges, and input formats.

Text Inputs

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

The control is valid when all applicable constraints are satisfied.

Email Inputs

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

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

Number Inputs

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

The entered number must satisfy the permitted range and any applicable step constraint.

Select Elements

<select name="size" required>
  <option value="">Choose a size</option>
  <option value="small">Small</option>
  <option value="large">Large</option>
</select>

The required select becomes valid when an acceptable option is selected.

Textarea Elements

<textarea name="message" required></textarea>

A required textarea must contain a value to satisfy its required constraint.

Custom Validity

JavaScript can establish custom validation errors using setCustomValidity(). A control with a nonempty custom validation message is invalid until that message is cleared.

Validation Attributes

HTML validation attributes define the requirements that a control must satisfy to match :valid.

Attribute or Type Validation Purpose
requiredRequires a value or selection.
minlengthSets a minimum text length.
maxlengthSets a maximum text length.
patternRequires a text value 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 all applicable constraints to match :valid.

Constraint Applicability

Not every validation attribute applies to every input type. For example, min and max are useful for numeric and certain date-related controls, while pattern applies to supported text-based input types.

:valid vs. :invalid

The :valid and :invalid pseudo-classes represent opposite constraint validation states.

Feature :valid :invalid
Matches controls that pass validationYesNo
Matches controls that fail validationNoYes
Requires user interactionNoNo
Can match on page loadYesYes

Combined Example

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

Initial Validation States

An empty required input can match :invalid immediately, while an empty optional input can match :valid immediately.

Mutually Exclusive States

A control participating in constraint validation cannot match both :valid and :invalid at the same time.

:valid vs. :user-valid

The :valid pseudo-class responds to the current validity of a control, while :user-valid also considers user interaction.

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

Immediate Valid Styling

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

Interaction-Based Valid Styling

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

Use :user-valid when success styling should generally wait until the user has interacted with a field.

Optional and Required Fields

Whether a field is required affects its initial validity state.

Optional Text Input

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

An empty optional text input is normally valid.

Required Text Input

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

An empty required text input is invalid.

Required and Valid

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

This selector limits valid-state styling to required inputs.

Optional and Valid

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

Optional inputs can match this selector even when they are empty, provided they satisfy all applicable constraints.

Filled Required Fields

Filling a required field does not automatically make it valid. Other constraints, such as email format or numeric range, must also be satisfied.

Form-Level Validation

The :valid pseudo-class can also match a form when all of its relevant form controls are valid.

HTML Example

<form id="signup-form">
  <label for="signup-name">Name</label>
  <input type="text" id="signup-name" name="name" required>
  <label for="signup-email">Email</label>
  <input type="email" id="signup-email" name="email" required>
  <button type="submit">Submit</button>
</form>

CSS Example

form:valid {
  border: 2px solid #228b22;
}
form:invalid {
  border: 2px solid #c62828;
}

The form matches :valid when its associated controls satisfy their validation requirements. It matches :invalid when a relevant control fails validation.

Fieldset Validation

A fieldset can also match :valid or :invalid based on the validity of its descendant form controls.

Native Submission Validation

Browsers normally prevent form submission when a participating control fails constraint validation, unless interactive validation has been disabled.

Server-Side Validation

Client-side validation does not replace server-side validation. All submitted values must still be checked by the server.

:valid Specificity

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

Specificity Examples

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

Specificity Example

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

The second selector has higher specificity and changes the border color when the input is valid, assuming other cascade factors are equal.

Accessibility

Validation feedback should be understandable to users who rely on keyboards, screen readers, or alternative visual presentations.

Do Not Rely on Color Alone

A green border alone may not clearly communicate a valid state to every user. Provide descriptive feedback when it is important to confirm successful validation.

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>

Focus Indicators

Do not remove visible keyboard focus indicators when applying validation styling.

Screen Reader Feedback

The :valid pseudo-class changes visual styling. It does not automatically announce that a field is valid or update custom ARIA attributes.

Avoid Premature Success Messages

Optional empty fields can match :valid. Use :user-valid or more specific selectors when you want to avoid suggesting that an untouched field has been completed.

Best Practices

  • Use :valid to style controls that satisfy their HTML validation requirements.
  • Define appropriate constraints with attributes such as required, pattern, and min.
  • Remember that optional empty controls can match :valid immediately.
  • Use :user-valid when success styling should wait for user interaction.
  • Combine :valid and :invalid when both validation states need styling.
  • Use descriptive labels and clear input instructions.
  • Do not rely on color alone to communicate validation results.
  • Preserve visible keyboard focus indicators.
  • Test form behavior with both valid and invalid values.
  • Always validate submitted data on the server.

:valid Example

This example demonstrates how :valid and :invalid respond to a required email field. The input starts in an invalid state because it is empty. Enter a properly formatted email address to make the input valid.

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

Browser Result

Play in Editor

Note: The required email field starts with a red border because it is invalid. Enter a valid email address to display the green border and background. Unlike :user-valid, the :valid pseudo-class does not wait for user interaction.

Browser Support

Baseline: Widely available. The :valid pseudo-class is supported in all major modern browsers, including Chrome, Edge, Firefox, Safari, and Opera.

For current compatibility information, visit Can I Use? and search for :valid.

Specifications

The :valid pseudo-class is defined in CSS Selectors Level 4 as a validity pseudo-class for form controls and related elements.

Selectors Level 4 - Validity Pseudo-Classes