Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

:not() selector not behaving the same between Safari and Chrome/Firefox

I am having a pretty hard time figuring out why the following code renders in blue in Safari but in red in Chrome and Firefox.

em:not(div) {
    color: red
}
em:not(p div) {
    color: blue
}
<p>
    <em>FOO</em>
</p>

https://jsfiddle.net/hzcLpf9L/

Apparently it looks like Chrome and Firefox do not support :not() CSS selectors with multiple levels in them. (Possible bug?)

I am very fond of :not() selectors and I develop with Safari, therefore when I discovered my website on Chrome I almost had an heart attack. Any explanation on why this strange behavior happens would be highly appreciated.

like image 956
Valentin Mercier Avatar asked Mar 14 '16 17:03

Valentin Mercier


2 Answers

Safari recently shipped the level 4 version of :not(), which allows complex selectors for arguments, putting it on par with jQuery's hitherto non-standard implementation. See the release notes. The current incarnation of :not() only allows a single simple selector for an argument, so a complex selector like p div will not work in today's browsers by design.

A complex selector is an expression consisting of one or more compound selectors separated by combinators such as descendant, >, ~ and +. A compound selector is a sequence of one or more simple selectors. div is a compound selector consisting of one simple selector, and p div is a complex selector consisting of two compound selectors (each of which consists of one simple selector), separated by a descendant combinator.

It is currently not known when this will land in the other browsers, though it's unlikely the new specification of :not() will change at this point — the current level 4 definition is a no-brainer and if the original WebKit strain is daring enough to implement it, then it's really only a matter of time before it makes its way into the other strains (including Blink).

After almost five grueling years of waiting since the FPWD, we might actually finally get to see a CR of selectors-4 real soon. Consider me pumped.

like image 50
BoltClock Avatar answered Nov 07 '22 05:11

BoltClock


From the spec:

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

and elsewhere in the spec:

A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.


The behaviour of Chrome and Firefox is correct. A descendant combinator may not appear in a simple selector (and thus, a :not pseudo-class)


This may change in Selectors Level 4. The current editor's draft allows more complex selectors. You appear to have encountered an experimental implementation.

like image 31
Quentin Avatar answered Nov 07 '22 06:11

Quentin