:invalid
Matches form fields whose value breaks an HTML validation rule, such as an empty required field or a malformed email address.
Example
#.error {
display: none;
color: #fda4af;
}
.field input:user-invalid {
border-color: #f43f5e;
}
.field input:user-invalid + .error {
display: block;
}<style>
.field { display: grid; gap: 6px; }
.field input { padding: 9px 12px; border: 2px solid #3f3f46; border-radius: 10px; background: #18181b; color: inherit; font: inherit; }
.field small { font-size: 13px; }
</style>
<div class="field">
<label for="email">Email address</label>
<input id="email" type="email" required placeholder="name@example.com">
<small class="error">Enter a valid email address.</small>
</div>Type text with no @ sign and click outside the field. The message only appears after that interaction, not right away on page load.
Definition and usage
#The :invalid pseudo-class connects CSS to built-in form validation. A field matches it when its value breaks one of the rules written in the HTML: required on an empty field, type="email" on text that isn’t an address, as well as pattern, min, or max. Its opposite is :valid.
The state updates live, with every keystroke. <form> and <fieldset> also match :invalid if they contain even one invalid field, which lets you, for example, dim the submit button.
The biggest trap: an empty field with required is invalid right from page load. Red borders before the user has typed anything feel like a scolding. The fix is :user-invalid, which only switches on after an interaction: after changing the value and leaving the field, or after trying to submit the form. It works in every major browser as of 2023. The older approach is :not(:placeholder-shown):invalid.
Syntax
#selector:invalid { property: value; }Common uses
#- Every invalid field at once. The empty required field glows red, even though no one has touched it yet.
- The opposite: fields with a valid value. Fix the second field into a full address to see the change.
- The red border only appears after an interaction. Change a field to an invalid value and click elsewhere.
input:not(:placeholder-shown):invalid
The older approach: the error only shows on fields that aren’t empty. An empty required field stays neutral.- The form matches
:invalidtoo, as soon as it has even one invalid field inside it.
Common uses in practice
#input:invalid
input:invalid { border-color: #f43f5e; }input:valid
input:valid { border-color: #10b981; }input:user-invalid
input:user-invalid { border-color: #f43f5e; }input:not(:placeholder-shown):invalid
input:not(:placeholder-shown):invalid { border-color: #f43f5e; }form:invalid
:invalid too, as soon as it has even one invalid field inside it.form:invalid {
outline: 2px dashed #f43f5e;
outline-offset: 4px;
}Browser support
#Widely available
Works in all modern browsers, phones included. You can use it without worry.
- Chrome
- Edge
- Firefox
- Safari
Good practices
#- Don’t show errors before the user starts doing anything. Highlight invalid fields through
:user-invalid, and save:invalidfor things like dimming the submit button. - Color alone isn’t enough, since not everyone can tell colors apart. Add a text message or an icon next to the field too.
- HTML and CSS validation is a convenience for the user, not a safeguard. The data still has to be checked on the server.
Related entries
#- :placeholder-shownMatches an input or textarea field that is currently showing its placeholder text, meaning it’s empty and has a placeholder attribute.
- :has()Selects an element based on what it contains or what follows it. Lets you style a parent according to its children.
- :focusMatches the element that has focus, meaning it currently receives keyboard input, such as a clicked form field.
- :disabledMatches disabled form elements, meaning ones that can’t be clicked, checked, or edited.
- :not()Selects elements that match neither the given selector nor any selector in the list.
- :focus-withinMatches an element that either has focus itself or contains an element with focus. Lets you highlight an entire form or card.
Spotted a mistake or missing an example? Write to us.