The CSS3 :not() selector

CSS & HTML, 25 August 2008, 68 comments

There isn’t a lot of information to be found about the :not() selector. The specifications only offer 3 lines of text and a couple of examples. So lets see what it can do!

The Specification

The negation pseudo-class, :not(X), is a functional notation taking a simple selector […] as an argument. It represents an element that is not represented by the argument.

What it says here, is that a selector with a :not() in it will match all elements that do not match what’s between the parenthesis.

A simple selector is a term used in the specifications. A simple selector is: a single element, attribute selector, class, id or pseude-class.

Examples of simple selectors:

body
*
[value="foo"]
.foo
#foo
:hover

Basically, any of the above type, but with only one selector.

The browsers

The :not() selector is only supported by modern browsers (Firefox, Safari and Opera), :not(IE).

Let’s take a look at what browsers allow you to do:

div:not(.home) {…}

This selects all div elements that do not have the class .home

div *:not(p) em {…}

This selects all em elements that are in an element (that is not a p element) and that are in a div element. so <div><strong><em>…</em></strong></div> is a match, but <div><p><em>…</em></p></div> is not.

input:not([type="file"]) {…}

This uses the attribute selector to select all input element, save for the file upload ones.

I was surprised to find out that

h2:not(.foo, .bar) {…}

also works. You can give the :not() selector a comma separated list as well! (Tested in Firefox 3) This is surprising, because it’s not documented as such in the specifications.

You can use the :not() selector as a part of a large selector. I’ve done this a few times in my current design:

li:not(.pingback) .comment-content p:first-child:first-line {…}
body:not(.home) h2 + p:first-letter {…}
.post:not(.first-post) a:hover {…}

The :not() selector is a nice addition to the CSS Tookit, and it can already be used in a way that allows for graceful degradation, such as I do on this website. If you have any nice experiences with :not(), please share them in the comments!