The :user-invalid
is a CSS pseudo-class that is under proposal in the CSS Selectors Level 4 working draft that selects a form element based on whether the value—as entered by a user—is valid when checked against the what is specified as an accepted value in the HTML markup after the end user has interacted with the form beyond that input. In fact, :user-invalid
has been called “The User Interaction Pseudo-class” because it is unique in identifying a user action in selecting an element.
Take the following HTML markup for a basic form with a numeric field:
<form>
<label for="quantity"> Quantity:</label>
<input id="quantity" max="10" min="0" type="number" value="11" />
<!-- Rest of the form... -->
</form>
The numeric range set by the HTML markup for the input is between 1
and 10
but the default value has been set to 11
. That means the value is invalid as soon as the form loads.
However, the :user-invalid
pseudo-class will not take effect until after the user has actually interacted with the form beyond entering it in the field. That interaction is the difference between :user-invalid
and :invalid
. The same principle applies for entered form values that are set by :in-range
, :out-of-range
and :required
.
input:user-invalid {
color: red;
}
The following image illustrates the different states between :valid
, and :user-invalid
based on the HTML example above.
![](jpg/almanac-user-invalideb45.jpg)
The confusing thing with here is how closely related :invalid
and :user-invalid
are. If used together, it may be tough to distinguish the two:
input:invalid {
color: red;
}
input:user-invalid {
color: red;
}
![](jpg/alamanac-user-invalid-comparisoneb45.jpg)
:invalid
(center) and an invalid value entered by a user (right) can be tough to distinguishUsing one over the other or having distinct styling between the two might prove to be a better user experience in a real-life use case.
Browsers can decide how and when elements are matched
It’s worth calling out that when :user-invalid
matches form fields that are :invalid
, :out-of-range
, or blank but :required
, it’s doing so “between the time the user has attempted to submit the form and before the user has interacted again with the form element.” However, the spec leaves room for browsers to make their own decisions for when elements match:
User-agents may allow them to match such elements at other times, as would be appropriate for highlighting an error to the user. For example, a UA may choose to have
:user-invalid
match an:invalid
element once the user has typed some text into it and changed the focus to another element, and to stop matching only after the user has successfully corrected the input.
Once the value that the user has entered is determined to be an invalid entry, we can select the element.
Browser support
It’s only Firefox at the time of writing, which was implemented :user-invalid
in Firefox 88. The Chromium project has an open bug ticket (star it!) to implement it in Blink-based browsers (i.e. Chrome and Edge). There’s an open WebKit ticket to add support in Safari as well.
Check caniuse for the latest browser support.
More information
- CSS Selectors Level 4 Specification
- MDN Specification for
:-moz-ui-invalid
- Chromium Ticket #1156069
- WebKit Ticket #222267