Does :not() negation accept descendant selectors?

2019-01-12 12:06发布

问题:

This question already has an answer here:

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

I've been using the :not() pseudo-class to style things without the need to override it with a second unnecessary declaration to undo the first one, but now I came across a weird behaviour where Safari accepts descendant selectors within the :not(), but Chrome doesn't.

I used something like a:not(.blue a).

I searched for answers, but I still don't fully understand the reason.
Are descendant selectors really allowed by the spec?

Here's a demo:

a:not(.blue a) {
  color: red;
}
<div><a>this one should be in red</a></div>
<div class="blue"><a>this one shouldn't</a></div>

http://codepen.io/oscarmarcelo/pen/YqboQJ?editors=1100

回答1:

In Selectors Level 3, the answer would be NO. The :not() notation accepts only simple selectors.

6.6.7. The negation pseudo-class

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.

What is a simple selector?

From selector syntax:

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

Nothing about a descendant selector.

HOWEVER, in Selectors Level 4, :not() accepts complex selectors, which would include descendant combinators. Browser support is still quite weak for this specification.