令人惊讶的 CSS 选择器

2023-12-27  本文已影响0人  涅槃快乐是金

最近,我在学习 CSS 嵌套的过程中深入研究了新的 & 选择器,特别是与 :is()选择器的关系。我听说它的行为类似于 :is() 选择器,在研究的过程中,我学到了很多关于这些新选择器如何工作的知识。

首先要知道的是,:is()及其兄弟 :not():has()和 :where() 是一种新的选择器类型,称为函数伪类。我们长时间以来一直有简单的伪类,比如 :hover,但是将选择器列表作为参数传递的能力是将这四个伪类区分为一个新类别的关键点。

让我们先简要回顾一下今天将要讨论的新选择器,然后我们将深入探讨我学到的一些令人惊讶的事情:

选择优先级

这些新选择器最有趣的之一是它们与选择优先级的关系。 ID 的优先级高于类,而类的优先级高于元素选择器。

#unique { color: red; }
.intro { color: orange }
p { color: green; }
<p class="intro" id="unique">This will be red</p>

这个段落将是红色的,因为 ID 选择器是最高优先级的。

那么对于接受逗号分隔的选择器列表的伪类,比如 :is():not():has()会发生什么呢?伪类的优先级由列表中最具体的选择器确定。

:is(#unique, p) { color: red; }
.intro { color: green; }
<p class="intro">This will also be red</p>

你可能期望段落是绿色的,因为它没有 #unique ID。但在这种情况下,列表中最具体的对象是 ID,因此它将成为 :is()选择器的权重。因此,即使在这种情况下 ID 不适用,它仍会影响特异性。

这种行为的一个有趣变化是 ·:where() ·选择器,它的行为与 :is() 选择器完全相同,唯一的区别是它始终具有零权重。

:where(#unique, .intro) { color: red; }
p { color: green; }
<p class="intro" id="unique">This will be green.</p>

这在编写希望易于覆盖的 CSS 时特别有用,例如 WordPress 主题或第三方库中的默认样式。

选择器列表

在标准 CSS 中构建选择器列表时,如果列表中的任何选择器是无效的,比如 .valid-class :invalid-pseudo-class,整个样式块都将被忽略。

现在,你可能会想“谁会在他们的 CSS 中添加无效的选择器呢?”你可能需要这样做的一个例子是浏览器前缀的选择器。比如,如果你想使用 :fullscreen 伪类,但需要支持一些只理解 webkit 前缀版本的旧浏览器,你需要编写如下代码:

:-webkit-full-screen { border-color: green; }
:fullscreen { border-color: green; }

如果尝试使用逗号分隔的列表,那么不理解 :fullscreen 的浏览器会失败。因此,你必须为每个选择器重复样式块。

值得庆幸的是,大多数新的伪类,比如:is():where(),都接受规范称之为宽容的选择器列表,这意味着列表中的任何无效选择器都将被忽略,但仍将使用有效的选择器。

:is(.valid-class, :invalid-pseudo-class) { ... }

浏览器会忽略 :invalid-pseudo-class,但仍然应用规则到 .valid-class。

不幸的是,:not()伪类使用的是不宽容的选择器列表,因此将任何无效选择器添加到列表中将导致整个样式块被忽略。然而,有一个相当愚蠢的解决方案:只需将选择器列表包装在:is()伪类中:

:not(:is(.valid-class, :invalid-pseudo-class)) { ... }

这将使 :is()从列表中剥离任何无效的选择器,并将剩余的选择器传递给 :not()

直到最近,:has()伪类也使用了宽容的选择器列表,但由于与 jQuery 存在冲突,他们不得不在 2022 年底撤销这一更改。现在,如果可能有一个无效的选择器传递给:has(),你可以使用相同的 :has(:is()) 技巧来防止它破坏。

需要注意的事项

关于这些新选择器,如果不小心的话可能会让你感到惊讶。以下是一些我注意到的事项:

嵌套选择器

好的,让我们谈谈我为什么要深入研究这个话题的原因——& 嵌套选择器!这个新选择器是为了 CSS 嵌套而添加的(尽管它也可以用于其他上下文,比如 CSS 作用域)。在 CSS 嵌套中使用时,&将被替换为父样式规则的选择器,其选择优先级与是否使用:is() 相同

a {
  &:hover { color: rebeccapurple; }
}

/* will be treated like */
:is(a):hover { color: rebeccapurple; }

在大多数情况下,这不会有任何影响,只是值得注意,但可能会产生一些的副作用。

#card, .card {
  .featured & { color: cornflowerblue; }
}

/* will be treated like */
.featured :is(#card, .card) { color: cornflowerblue; }

由于 & 选择器包含一个 ID,生成的规则将使用该 ID 的优先级。因此,在使用& 时,要注意潜在的意外优先级冲突。

值得注意的是,由于嵌套选择器的行为类似于:is() 选择器,它也不能表示伪元素。

a, a::before, a::after {
  color: red;

  &:hover { color: blue; }
}

/* will be treated like */
a, a::before, a::after {
  color: red;
}
a:hover {
  color: blue;
}

正如你所看到的,伪元素在最终规则的悬停状态中被忽略了。

结论

我开始学习一下 CSS 嵌套的工作原理,特别是新的 & 选择器,结果却深入研究了:is()选择器及其衍生物。希望这对你也有用。

上一篇下一篇

猜你喜欢

热点阅读