<Glazblog/>

Safari and :not() CSS3 pseudo

Not sure if it's public or not - did I miss a post from Hyatt about it - but I just discovered Safari has extended the grammar and features of the :not() negation pseudo-class from the CSS 3 Selectors module. At least my Windows version of Safari does it. In the spec, the argument of the functional pseudo-class must be a simple selector. In other terms, it can be an ID selector, a class selector, an attribute selector or any other simple selector but not a combination of several simple selectors. :not(#foo) is valid while :not(#foo.myClass) is not.

Safari extends the spec and allows the argument to be a sequence of simple selectors like the :not(#foo.myClass) above. Well. It's NOT only a matter of readability and conciseness for CSS because

A > B:not(CD) { ... }  (where A, B C and D are all simple selectors)

is not strictly equivalent to

A > B:not(C), A > B:not(D) { ... }

and is not equivalent at all to

A > B:not(C) { ... }
A > B:not(D) { ... }

in particular if A B and C are valid but D is an invalid simple selector...

The specificity also matters, and I suspect (and hope) Safari takes under consideration all simple selectors in the argument of that extended :not().

Comments

1. On Tuesday 4 March 2008, 16:32 by Francis Gagné

Firefox allows to combine multiple :not() pseudo-classes on one sequence. So A > B:not(CD) would be equivalent to A > B:not(C):not(D).

2. On Tuesday 4 March 2008, 16:37 by Daniel Glazman

@Francis : NO !!! NOT(A AND B) is NOT(A) OR NOT(B)...

3. On Tuesday 4 March 2008, 18:12 by Francis Gagné

Huh, there must be something I don't understand, because what I understood from your post is the opposite of your comment... Is that the point?

4. On Tuesday 4 March 2008, 22:38 by Blair McBride

I was intrigued by this, so had a look myself. Have a look at this in the latest Safari beta: http://theunfocused.net/webtests/cs...

The selector:

A > B:not(CD) { ... }

Does indeed seem to act like:

A > B:not(C):not(D) { ... }

5. On Tuesday 4 March 2008, 22:48 by Blair McBride

Er, scratch that - I added another test case to the .html file in my previous comment.

So, Daniel is correct, in that it works like: NOT(A AND B) is NOT(A) OR NOT(B)

Maybe its too early in the morning for me to be doing stuff like this...

6. On Tuesday 4 March 2008, 23:45 by David Hyatt

Oh. I thought the spec supported a chain of simple selectors, so that's what I implemented in WebKit. Safari has always worked this way.

I have no idea why the spec limits what goes inside :not.

7. On Wednesday 5 March 2008, 00:59 by Blair McBride

"I have no idea why the spec limits what goes inside :not."

Probably because its confusing overwise... personally, I would expect A > B:not(CD) to work like A > B:not(C):not(D)

But effectively its working like A > B:not(C, D)

Which is just mixing syntax's... and confusing.

8. On Wednesday 5 March 2008, 11:58 by David Hyatt

Shrug, I don't think it's confusing at all. It's simple logic.

AB = "and"(&) in CSS.

A, B = "or" (|) in CSS.

:not = "not" (^) in CSS.

DeMorgan's Law says that:

^(A & B) = ^A | ^B

and that:

^(A | B) = ^A & ^B

Expressing that in CSS is just ... well... logic. :)

:not(AB) = :not(A), :not(B)

:not(A, B) = :not(A):not(B)

Why would you expect it to work differently? Note the original implementation worked with compound selectors too. I think it's silly that :not was limited to simple selectors (and even sillier that it has been apparently limited to a single selector).

I doubt we will drop this enhancement. In fact, we'll probably expand :not to support compound selectors in the future.

9. On Wednesday 5 March 2008, 12:16 by Daniel Glazman

@hyatt: extending the value of :not() to a selector raises a few important questions:

1. what's the specificity of :not() in that case ?
2. do you allow :not() in :not() argument ? (why not, eh ?)
3. do you plan to support groups of selectors too ? :not (A, B) ?
4. if you allow a real selector as argument of :not(), the following

#foo > .bar:not(div p) > span.mySpan

adds more than one tree constraint to the intermediate element. That's a rather major change in terms of selectors spirit. Probably in terms of implementation too. Furthermore, and even if it's very powerful, I am not sure it increases readability...