Safari and :not() CSS3 pseudo
By glazou on Tuesday 4 March 2008, 12:05 - CSS and style - Permalink
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
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).
@Francis : NO !!! NOT(A AND B) is NOT(A) OR NOT(B)...
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?
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) { ... }
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...
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.
"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.
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.
@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...