An error state that waits its turn
Caveat:invalid matches from the moment the page loads, so an empty required field is red before anyone has typed a character. :user-invalid waits until the field has been interacted with.
FallbackWhere it is unsupported nothing turns red at all, which is the safe direction. Keep the browser message as the real error and use colour only to point at it.
/* not :invalid, that fires on load */
input:user-invalid { border-color: #e06c6c; }
input:user-valid { border-color: #93c47d; }
Published
Questions
Why is my required field red before anyone has typed anything?
You are styling :invalid, which matches from the moment the page loads — an empty required field is invalid immediately. :user-invalid waits until the field has actually been interacted with and left wrong.
What counts as interacting with the field?
Changing the value and moving on, or submitting the form. Focusing a field and leaving it untouched is not enough, which is the whole point: a form you have only tabbed through never lights up red.
What happens where :user-invalid is unsupported?
Nothing turns red at all — the safe direction to fail. Keep the browser's own validation message as the real error and let colour only point at it.