Next-sibling 组合器不应该与复杂的选择器一起使用

Next-sibling combinator should not work with complex selectors

TL;DR

根据规范,以下内容不应该起作用,但它确实起作用:

.a .b + .b {margin-top:20px;}

详情

According to the spec the "Next-sibling combinator" (or "adjacent sibling combinator") should only work for "sequences of simple selectors", which themselves are defined 作为

... a chain of simple selectors that are not separated by a combinator.

在我上面给出的示例中,左侧的选择器 .a .b 包含一个 "descendant combinator"(由空格表示),因此不应被允许。

有趣的是,以下确实根本不起作用:

.b + .a .b {margin-top:20px;}

为什么我的介绍性示例适用于现代浏览器?

the specification中您可以阅读:

The next-sibling combinator is made of the "plus sign" (U+002B, +) character that separates two sequences of simple selectors. The elements represented by the two sequences share the same parent in the document tree and the element represented by the first sequence immediately precedes the element represented by the second one.

没有人说它只适用于“简单选择器的序列”。它只是说 + 字符分隔两个简单选择器序列,除此之外它没有任何限制,因此您可以有更多选择器。

让我们考虑以下示例:

.a .b + .b
.b + .b
span.a:not(.b) .b + .b > div

在所有这些中我们都有 .b + .b 部分,其描述为:

the "plus sign" (U+002B, +) character that separates two sequences of simple selectors.


如果您在规范的开头阅读,您会发现确认这一点的通用规则:

A selector is a chain of one or more sequences of simple selectors separated by combinators. One pseudo-element may be appended to the last sequence of simple selectors in a selector.

A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence.

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

基本上我们可以

Seq_simple_selectors + Seq_simple_selectors Seq_simple_selectors > Seq_simple_selectors

然后在每个 Seq_simple_selectors 里面我们可以有这样的东西:

 div.a.b#id::before

如果我们考虑你的例子 .a .b + .b 你有 3 个序列,每个序列只有一个简单的选择器。

你的第二个例子也很好,如果你有正确的 HTML 可以工作:

.b + .a .b {
  background: red;
  height: 20px;
}
<div class="b"></div>
<div class="a">
  <div class="b"></div>
</div>


无效的是有这样的东西.b + > .a。在这种情况下,我们没有:

the "plus sign" (U+002B, +) character that separates two sequences of simple selectors.

但是我们在简单选择器序列和组合器选择器之间有一个分离。

在尝试理解选择器语法时,"sequences of simple selectors" 的新名称是 compound selector. The definitions of compound selector and combinator, and many other terms, in selectors-4 are much clearer than the ones in selectors-3, to such an extent that I no longer recommend using selectors-3 as a reference

A compound selector is a sequence of simple selectors that are not separated by a combinator, and represents a set of simultaneous conditions on a single element.

A combinator is a condition of relationship between two elements represented by the compound selectors on either side.

这应该会大大减少可能引发您的问题的混淆,因此我将在我的回答中专门使用新名称。

在您的第一个示例中,+ 组合器出现在两个复合选择器之间,每个复合选择器都包含一个简单选择器 .b。换句话说,.b + .b 不是 a 复合选择器...因为它是 two 复合选择器和组合器。您的第一个示例是一个有效的复杂选择器,由三个复合选择器和两个组合器组成。

一个有效的复杂选择器可以包含多少个复合选择器没有限制,只要每两个复合选择器之间是一个组合器,而不是一些意外的标记。这意味着一个复杂的选择器实际上可以只包含一个复合选择器,而没有组合器。这三个示例是有效的复杂选择器(使用 selectors-4 grammar 中的符号):

<complex-selector> = <compound-selector>
<complex-selector> = <compound-selector> <combinator> <compound-selector>
<complex-selector> = <compound-selector> <combinator> <compound-selector> <combinator> <compound-selector>

另请记住,不匹配任何内容的复杂选择器仍然有效。

就此而言,.b + .a .b 似乎不起作用的原因是因为它与 .a .b + .b 具有 不同的含义,而您的 HTML 与该复杂选择器阐明的条件不匹配。

.a .b + .b表示

Match any .b
that is the next sibling of another .b
that is a descendant of an .a.

.b + .a .b表示

Match any .b
that is a descendant of an .a
that is the next sibling of another .b.

请注意,另一个 .b 是每个上下文中 不同元素 的前一个兄弟。如果你的 HTML 满足一个而不满足另一个,那么它只会匹配一个而不匹配另一个。但是,以下片段将满足两者(因此匹配两者):

.a .b + .b { color: red; }
.b + .a .b { font-style: italic; }

code { display: block; }
<div class="b"></div>
<div class="a">
  <code class="b">.b</code>
  <code class="b">.b + .b</code>
</div>