2 min read

CSS :valid and :invalid Pseudo-classes

The :valid and :invalid pseudo-classes allow you to style form elements based on whether their current value meets the validation constraints set by HTML attributes (like type, required, min, max, pattern).

1. :valid

The :valid pseudo-class represents any <input> or other form element whose content validates successfully against all its validation constraints.

/* Give a visual cue that the input is correct */
input:valid {
  border-color: green;
  background-image: url('check.svg');
}

2. :invalid

The :invalid pseudo-class represents any form element whose content does not validate successfully.

/* Highlight errors */
input:invalid {
  border-color: red;
  background-color: <a href='/?search=%23ffe6e6' class='obsidian-tag'>#ffe6e6</a>;
}

3. Validation Constraints

These pseudo-classes react to standard HTML5 validation attributes:

  • required: The field must have a value.
  • type: The value must match the type (e.g., type="email", type="number").
  • min / max: The numeric value must be within range.
  • minlength / maxlength: The string length must be within range.
  • pattern: The value must match a specific Regex.
<input type="email" required>
<!-- 
  If empty -> :invalid (because required)
  If "hello" -> :invalid (not an email)
  If "hello@example.com" -> :valid
-->

4. Preventing Premature Validation

A common UX issue is that :invalid styles apply immediately when the page loads (e.g., empty required fields show as red errors before the user even touches them).

To fix this, you can combine it with :not(:placeholder-shown) or :focus.

/* Only show invalid style if the user has typed something (placeholder is gone) */
input:not(:placeholder-shown):invalid {
  border-color: red;
}

/* Or only show when focused */
input:focus:invalid {
  outline: 2px solid red;
}

programming/css/css programming/css/pseudo-classes-and-pseudo-elements programming/css/required-and-optional-pseudo-classes