W3docs

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 its min/max range.
  • A type="url", type="date", or type="tel" field holding well-formed data.
  • A field with a pattern attribute whose value matches the regular expression.
  • A required field 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 no required, pattern, or length limits) is always considered valid — it will match :valid even 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 :focus or the :user-invalid / :user-valid pseudo-classes.
  • Specificity matters: input:valid and input:invalid have the same specificity, so the rule declared later in the stylesheet wins for borderline cases. Keep the order intentional.

Version

HTML Living Standard

HTML5

Selectors Level 4

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 110 range.

  • :invalid — the exact opposite: matches controls that fail validation.
  • :required and :optional — match based on whether a control is required.
  • :in-range — matches numeric/date inputs whose value is inside min/max.

Practice

Practice
What is the usage and function of the 'valid' CSS pseudo-class?
What is the usage and function of the 'valid' CSS pseudo-class?
Was this page helpful?