Skip to content

CSS Tutorial CSS Forms

Form Validation Styles

Lesson 132 of 182 2 min read By Deepak Paswan Updated Oct 4, 2026

HTML can validate fields for you: required, type="email", minlength, pattern. CSS can then show the result.

:valid and :invalid

index.html
HTML
<style>
  input { padding: 9px 12px; border: 2px solid #b9b2ad; border-radius: 6px; font: inherit; }
  input:valid   { border-color: #27ae60; }
  input:invalid { border-color: #c0392b; }
</style>
<input type="email" placeholder="you@example.com" required>

Try it: the empty required field is red straight away, before you have typed anything. That is a poor experience, and it is the main problem with :invalid.

Wait until the user has interacted: :user-invalid

:user-invalid and :user-valid apply only after the user has interacted with the field. This is how it should have worked in the first place, and current browsers support it.

index.html
HTML
<style>
  input { padding: 9px 12px; border: 2px solid #b9b2ad; border-radius: 6px; font: inherit; }
  input:user-invalid { border-color: #c0392b; background: #fdf2f2; }
  input:user-valid { border-color: #27ae60; }
</style>
<input type="email" placeholder="Type, then click away" required>

Type something that is not an email and then click elsewhere to see the error state.

Do not use color alone

Always add a text message, and link it to the field so screen readers read it.

index.html
HTML
<label for="e">Email</label>
<input id="e" type="email" required aria-describedby="e-help">
<p id="e-help" class="error">Enter a valid email address, for example name@example.com.</p>
style.css
PHP
.error { color: #b00020; font-size: 0.875rem; }
.error::before { content: "⚠ "; }

The icon and text mean people who cannot see red still get the message.

lightbulb
Make the message specific
“Invalid input” helps nobody. “Password needs at least 8 characters” does.