:where() 也拥有一个很酷的权重技巧。

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

最近,关于 :is() 伪类选择器 的讨论非常热烈,这可能是因为 Safari 14 已经支持它,现在所有主要浏览器都支持它。Miriam 在推特上谈论它,Kevin Powell 制作了一个视频,Šime 将其加入了 Web 平台新闻,Robin 也 提到了它。Bramus 用这“三个重要的事实”强调了它

1. :is() 的选择器列表具有容错性
2. :is() 的权重与其最具体的参数相同
3. :is() 不适用于伪元素选择器 (目前)

此外,当然,它的主要功能是使原本冗长、复杂且容易出错的选择器更容易编写。权重方面尤其有趣。Miriam 指出了一些可以使用它的技巧,比如在不实际选择任何元素的情况下提高权重。

假设你想使用 .button 类进行选择,但希望它拥有极高的权重

:is(.button, #increase#specificity) {
  /* specificity is now (0, 1, 0, 0) instead of (0, 0, 1, 0)
}

我过去做过一些类似的愚蠢操作

.button.button.button {
  /* forcing the selector to be (0, 0, 3, 0) instead of (0, 0, 1, 0) */
  /* doesn't actually require element to have three button classes lol */
}

:is() 的技巧对我来说似乎更易于理解。

但是,如果你想以相反的方式处理权重并将其降低呢?好吧,这就是 :where() 伪类选择器的全部意义所在。从功能上讲,它与 :is() 完全相同。你提供一个用逗号分隔的选择器列表作为选择器链的一部分,它就会执行选择,并且具有相同的容错性。不同的是,整个 :where() 部分的权重为零 (0)。

Kevin 在视频中展示了 :is() 的一个有趣的陷阱

.card :is(.title, p) {
  color: red;
}

.card p {
  color: yellow;
}

你可能会认为 yellow 会胜出,但由于顶部 :is() 选择器中存在 .title,因此该选择器的权重 (0, 0, 2, 0) 会胜过下面的 (0, 0, 1, 1)。

在这里,我们可以考虑使用 :where()!如果我们改为使用 :where() 伪类选择器

.card :where(.title, p) {
  color: red;
}

.card p {
  color: yellow;
}

那么 yellow 就会获胜,因为顶部选择器的权重降低到 (0, 0, 1, 0),低于底部选择器的 (0, 0, 1, 1)。

应该使用哪一个?你知道,我不确定这里是否有非常可靠且经过时间考验的建议。至少我们都拥有这两种选择,这意味着如果你遇到麻烦,你都有工具可以使用。时间告诉我,保持权重较低 通常是一个更健康的选择。这为你提供了覆盖的空间,而如果你权重过高,你的选择就会减少。但是 :where() 的零权重非常极端,我可以看到这也会导致令人困惑的时刻。所以我的直觉告诉我,你可能应该先从 :is() 开始,除非你注意到需要混合使用权重更高的选择器;如果确实需要,则退回到 :where()