【问题标题】:What is the difference between :where() and :is()?:where() 和 :is() 有什么区别?
【发布时间】:2021-05-12 00:17:36
【问题描述】:

CSS 最近添加了伪类:where():is(),我不明白什么时候使用。两者都可用于选择多个元素。这是一个 sn-p,其中两个伪类都实现了相同的效果:

span {
  display: inline-block;
  height: 100px;
  width: 100px;
  background-color: grey;
  margin-bottom: 10px;
}

:is(.span1-1, .span1-2):hover {
  background-color: firebrick;
}

:where(.span2-1, .span2-2):hover {
  background-color: teal;
}
<span class="span1-1"></span>
<span class="span1-2"></span>
<br>
<span class="span2-1"></span>
<span class="span2-2"></span>

有人能举个例子,说明他们的行为不同吗?

【问题讨论】:

标签: css css-selectors


【解决方案1】:

如前所述,区别在于特异性。这在MDN 上有所提及,但由于某种原因并未突出显示。另一方面,spec 则更加明确:

4.4。特异性调整伪类::where()

Specificity-adjustment 伪类:where() 是一个功能性伪类,其语法和功能与:is() 相同。与 :is() 不同,:where 伪类及其任何参数都不会影响选择器的特异性——它的特异性始终为零。

有哪些用例?好吧,在您给出的示例中,它并不是非常有用。您没有任何需要匹配或不覆盖特异性的竞争选择器。你有一个基本的span 规则和一个自然覆盖它的:hover 规则(即,只是通过特异性的工作方式以及最初设计的特异性)。如果您不需要考虑任何特殊或特殊的样式,则使用:is():where() 并不重要。

:where() 在您拥有具有不必要的特定选择器的更通用规则时变得有用,并且这些规则需要被具有较少特定选择器的更专业规则覆盖。 MDN 和规范都包含一个(非常)常见用例的示例——我不想简单地重复 what's on MDN,所以这是规范中的一个:

以下是特异性启发式未能符合作者期望的常见示例:

a:not(:hover) {
  text-decoration: none;
}

nav a {
  /* Has no effect */
  text-decoration: underline;
}

但是,通过使用:where(),作者可以明确地声明他们的意图:

a:where(:not(:hover)) {
  text-decoration: none;
}

nav a {
  /* Works now! */
  text-decoration: underline;
}

与 MDN 不同,规范并没有真正用英文解释这个用例,所以我会。这里的“作者期望”是nav a CSS 规则(我称之为专门规则)将覆盖a:not(:hover) 规则(我称之为一般规则)。从表面上看,这不会发生。

因为:hover 伪类比类型选择器更具体,任何只有类型选择器的规则都无法覆盖适用于任何未悬停的a 的通用a:not(:hover) 规则.传统上,您需要匹配 a:not(:hover) 的特异性,最天真的是通过复制有问题的位:

a:not(:hover) {
  text-decoration: none;
}

nav a, nav a:not(:hover) {
  /* Works, but not ideal, to say the least */
  text-decoration: underline;
}

或者,通过添加选择器 increase specificity without affecting matching:

a:not(:hover) {
  text-decoration: none;
}

nav a:nth-child(n) {
  /* Works, but not ideal either */
  text-decoration: underline;
}

(或a:any-link,如果是链接)

:where() 的作用是允许您完全删除由:hover 添加的特异性,从而更容易为某些a 元素覆盖此规则,例如通过确保@ 中的a 元素无论光标是否在它们上方,987654355@ 总是带有下划线(因为nav aa 更具体)。

不寻常的是,因为它降低选择器的特异性,您通常会将:where() 与需要被覆盖的选择器一起使用,而不是覆盖选择器。另一方面,您使用 :is() 只是为了减少 CSS 规则中的选择器重复,例如通过改变

.span1-1:hover, .span1-2:hover

:is(.span1-1, .span1-2):hover

同时保留特异性(尽管请注意:is() does work differently once you're grouping selectors with different specificity amounts)。

这意味着虽然:where() 具有与:is() 相似的语法,但实际上它们是具有不同用例的两个不同的伪类。尽管如此,它们的用例确实部分重叠。例如,您可能需要在一般规则中减少选择器重复,这意味着使用:is(),但您更愿意使用:where() 来减少特异性。由于将单个:where() 应用于多个选择器很有用,因此允许它接受选择器列表,这样您就不必编写:where(:is(selector-list))。这一原则适用于许多其他新的伪类,例如:host():host-context():has(),以及4 级:not()

【讨论】:

  • :is() 和 :where() 有幸成为我第一次演讲 CSS 演讲的主题,我为此感到非常自豪,因为我因残疾而很少发言,但是我没有实际示例(link with timestamp),仅简要介绍具体性,因此此答案旨在取代我演讲的那一部分。
【解决方案2】:

来自我的评论

我猜这是选择器的特殊性, where() 很容易被覆盖,谨慎,而 is() 确实增加了特殊性。详情看这里https://developer.mozilla.org/en-US/docs/Web/CSS/:where

这里是来自您的 sn-p 的实时示例

span {
  display: inline-block;
  height: 100px;
  width: 100px;
  background-color: grey;
  margin-bottom: 10px;
}

p :is(.span1-1, .span1-2):hover {
  background-color: firebrick;
}

div :where(.span2-1, .span2-2):hover {
  background-color: teal;
}

 .span2-1:hover, 
 .span1-2:hover {
  background-color: darkorange;
}
<p><span class="span1-1"></span>
  <span class="span1-2"></span>
  <br>
</p>
<div>
  <span class="span2-1"></span>
  <span class="span2-2"></span>
</div>

注意:我一开始使用了一个包装器来增加特性,并设置了两个不同的容器来分派测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-15
    • 2016-07-25
    • 2011-02-14
    • 2018-02-18
    • 1970-01-01
    • 2011-04-16
    • 2020-08-16
    • 2014-02-24
    相关资源
    最近更新 更多