CSS :valid Pseudo Class
The CSS :valid pseudo-class matches form controls whose value passes validation. Learn how it works and try real examples.
The :valid pseudo-class matches any form control (such as <input>, <select>, or <textarea>) whose current value passes the element's built-in constraint validation. It gives you a CSS-only way to react to whether a field's data is acceptable — no JavaScript required.
A control is matched by :valid when it has validation constraints and its value satisfies all of them. Common triggers include:
- An
<input type="email">containing a correctly formatted address. - An
<input type="number">whose value falls within itsmin/maxrange. - A
type="url",type="date", ortype="tel"field holding well-formed data. - A field with a
patternattribute whose value matches the regular expression. - A
requiredfield that is not empty.
This pseudo-class is the counterpart of :invalid. Together they let you provide instant visual feedback as the user types. It is also closely related to :required, :optional, and :in-range.
Things to know
- A control with no constraints at all (for example a plain
<input type="text">with norequired,pattern, or length limits) is always considered valid — it will match:valideven when empty. - The match updates live as the user edits, not only on submit, so styles can flicker as someone types. To delay feedback, combine it with
:focusor the:user-invalid/:user-validpseudo-classes. - Specificity matters:
input:validandinput:invalidhave the same specificity, so the rule declared later in the stylesheet wins for borderline cases. Keep the order intentional.
Version
Syntax
CSS :valid syntax
:valid {
css declarations;
}Example of the :valid selector:
CSS :valid code example
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style>
input {
border: 1px solid #cccccc;
padding: 5px 10px;
}
input:valid {
background-color: #eeeeee;
}
</style>
</head>
<body>
<h2>:valid selector example</h2>
<form>
<input type="email" value="[email protected]" />
</form>
</body>
</html>In the given example, the grey background disappears the moment an invalid email address is entered, because the input no longer matches :valid.
Example with required fields and a green cue
A common pattern is to pair :valid with :invalid so every field shows a clear "good / not yet" state. Here, required fields turn green once they hold acceptable data and red while they do not:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style>
input {
padding: 6px 10px;
margin-bottom: 10px;
display: block;
border: 2px solid #cccccc;
}
input:valid {
border-color: #2eca6a;
}
input:invalid {
border-color: #e3382c;
}
</style>
</head>
<body>
<h2>Valid vs. invalid fields</h2>
<form>
<input type="email" placeholder="Email" required />
<input type="number" min="1" max="10" placeholder="1 to 10" required />
</form>
</body>
</html>Because both fields are required, they start out matching :invalid (empty), then switch to :valid once you enter a real email and a number within the 1–10 range.
Related pseudo-classes
:invalid— the exact opposite: matches controls that fail validation.:requiredand:optional— match based on whether a control is required.:in-range— matches numeric/date inputs whose value is insidemin/max.