The :invalid selector allows you to select <input> elements that do not contain valid content, as determined by its type attribute. :invalid is defined in the CSS Selectors Level 3 spec as a “validity pseudo-selector”, meaning it is used to style interactive elements based on an evaluation of user input.

This selector has one particular use: providing a user with feedback while they are interacting with a form on the page. The example below uses CSS to turn the “Email” fields red or green, responding to the whether or not the contents match a valid email address pattern:

Check out this Pen!

Note how the first <input> (“Email”) is green—valid—even when there is no content in the field. This is because the input is optional, so leaving it blank would result in a valid form submission. To fix this behaviour, the second <input> has a “required” attribute, which means that a blank field would result in an invalid form submission.

Points of Interest

  • :invalid can be “chained” with other pseudo-selectors: like :focus to only validate when the user is typing, :before or :after to generate icons or text to provide more user feedback, or attribute selectors like input[value=""] to only validate input fields containing content.

Other Resources

Browser Support

Chrome Safari Firefox Opera IE Android iOS
10.0+ 5.0+ 4.0+ 10.0+ 10+ Nope Nope

:invalid was introduced in CSS Selectors Module 3, which means old versions of browsers do not support it. However, modern browser support is getting better. If you require older browser support, either polyfill, or use these selectors in non-critical ways á la progressive enhancement, which is recommended.


  1. c
    Permalink to comment#

    this is ok.

  2. Saher Team
    Permalink to comment#

    Solidify Your Examples:

    Email: youremail@domain.com
    Email (required) : chris@domain.com > becomes Valid _

  3. Diego Leme
    Permalink to comment#

    Bug in IE10+ usign pseudo-elements

  4. Neil Osman
    Permalink to comment#

    Hi Chris, you may want to update this content as it contain a slight inaccuracy – in “Points of interest” it says we can chain :invalid to :before :after to display some ‘content’ on inputs, but as a matter of fact we can’t use ::after and ::before on inputs (regardless of chaining).

    input[required]:valid::after {
    content: ‘not a chance’;

  5. h
    Permalink to comment#


  6. h
    Permalink to comment#


  7. David
    Permalink to comment#

    It should be noted that [value=”] only captures the initial state of the element, which makes it kind of useless as a selector.

  8. Guido
    Permalink to comment#

    Can you update the Browser Support table?

    According to caniuse.com android and iOS now support :invalid pseudo-class.

    @link http://caniuse.com/#search=%3Ainvalid

Leave a Comment

Posting Code

We highly encourage you to post problematic HTML/CSS/JavaScript over on CodePen and include the link in your post. It's much easier to see, understand, and help with when you do that.

Markdown is supported, so you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences like this:

  function example() {
    element.innerHTML = "<div>code</div>";

We have a pretty good* newsletter.