CSS Form Validation Selectors - :valid, :invalid, :required
Style HTML form validation states with :valid, :invalid, :required, and :optional. Create user-friendly form feedback using CSS-only validation styling.
Detailed Explanation
CSS Form Validation Pseudo-classes
CSS provides pseudo-classes that match form elements based on their validation state. These allow you to style valid and invalid inputs without JavaScript.
Available Selectors
| Selector | Matches |
|---|---|
:valid |
Elements passing validation |
:invalid |
Elements failing validation |
:required |
Elements with required attribute |
:optional |
Elements without required |
:in-range |
Number/date inputs within min/max |
:out-of-range |
Number/date inputs outside min/max |
:placeholder-shown |
Inputs showing placeholder |
:user-valid |
Valid after user interaction (CSS4) |
:user-invalid |
Invalid after user interaction (CSS4) |
Basic Validation Styling
input:valid {
border-color: green;
background-image: url('checkmark.svg');
background-position: right 8px center;
background-repeat: no-repeat;
}
input:invalid {
border-color: red;
background-image: url('error.svg');
background-position: right 8px center;
background-repeat: no-repeat;
}
The "Too Eager" Problem
A common complaint is that :invalid styles show immediately, before the user has had a chance to type. The solution uses :placeholder-shown or the newer :user-invalid:
/* Only show invalid styles after user interacts */
input:not(:placeholder-shown):invalid {
border-color: red;
}
/* CSS Selectors Level 4 (Chrome 119+, Firefox 88+) */
input:user-invalid {
border-color: red;
}
Required Field Indicators
input:required {
border-left: 3px solid #3b82f6;
}
/* Show asterisk via label */
label:has(+ input:required)::after {
content: " *";
color: red;
}
Range Validation
input[type="number"]:in-range {
border-color: green;
}
input[type="number"]:out-of-range {
border-color: red;
background: #fff0f0;
}
Specificity
All form validation pseudo-classes have specificity (0, 1, 0).
Use Case
CSS form validation selectors reduce the need for JavaScript-based validation styling. They provide instant visual feedback for email formats, required fields, number ranges, and pattern matching. When combined with :placeholder-shown or :user-invalid, they create a polished user experience where error styling only appears after the user has interacted with the field.