子选择器和后代选择器在性能上有区别吗?

Is there a difference in performance between the child and descendant selectors?

我可以使用子组合器 > 或仅 space 来表示任何后代来编写 CSS 选择器。例如,我有这个 HTML 代码:

<span id='test'>
    <a href="#">Hello</a>
</span>

我可以用以下两种方式编写我的 CSS 代码:

#test > a {
    ...
}

#test a {
    ...
}

关于性能,编写以下 CSS 代码的最佳方法是什么?

请注意,select或两者都不会为您提供相同的输出!在您的示例中,确实如此。

但是让我们检查下一个 HTML 代码,它包含两个 link。

<div id="test">
    <p> lorum ipsum <a href="#">here</a> dolor </p>
    <a href="#">read more</a>
</div>

正文之间有一个link,段落后有一个link,让用户阅读更多的文字。 (比如在新闻网站上)。

如果你使用

#test a {
    ...
}

那么你将 select 都 link。

如果你使用

#test > a {
    ...
}

它只会 select #test 的直系后代 link,即读 more-link !那是因为 > 是一个 child combinator。段落中的 link 不会被 select 编辑。

以下是向您展示差异的片段。

#test a {
  color: red;
}
#test > a {
  font-weight: bold;
  font-size: 18px;
}
<div id="test">
  <p>lorum ipsum <a href="#">here</a> dolor</p>
  <a href="#">read more</a>
</div>

如您所见,第二个 CSS 规则只编辑了第一个子 <a> 元素("read more" link)。

现在,回到关于您所处情况的性能的问题:如果您同时使用 select 或在下一个 HTML 部分

<div id="test">
    <a href="#">Hello</a>
</div>

这里的性能是一样的。

-- edit1: 对上面这句话的澄清--

当使用 selector 时,它会从右到左检查。在 this 情况下,正文中有一个 div,div 中有一个 link 元素,性能相同。这是因为当使用 #test > a 时,它会检查所有 link 以查看其父项是否具有 id="test"。它不会进一步遍历树。

当使用 #test a 时,它会检查 link 元素(直到根)的所有父元素以查看它是否具有 id="test"。由于在这种情况下,div 已经在第一次父检查时找到,因此不必进一步遍历树。

但在其他情况下,当 div 不是文档中的唯一元素时,它当然会有所不同。您不能在这里比较差异,因为如前所述,结果不同。除非你保证给定的div下没有second-levellink。那么,使用>当然更快。

-- 结束编辑--

但是,如果此人扩展了上述 div 的内容,he/she 可能会面临意想不到的 CSS 样式。

但要了解整体性能,这实际上取决于您想要通过 CSS(设置所有 link 还是仅设置第一级?)和 DOM 实现的目标div#tree 中的树(树的深度?)。

Browsers parse selectors from right to left.

然后,如果您使用 #test > a,对于页面中的每个 a 元素,浏览器会检查其父元素是否具有 id="test".

但是如果您使用 #test a,对于页面中的每个 a 元素,浏览器会检查其某些祖先是否具有 id="test"。文档中不应该有很多这样的元素,所以浏览器可能必须检查每个 a.

的所有祖先

我没有做任何测试,但我预计检查所有祖先比只检查父要慢。

所以可能 #test > a 更快。