使用 :where() 的特异性作为 CSS 重置

Avatar of Mojtaba Seyedi
Mojtaba Seyedi

DigitalOcean 为您的每个旅程阶段提供云产品。 立即开始使用 $200 免费积分!

我不知道你怎么样,但我经常在我的 CSS 中写这三个声明

ul {
  padding: 0;
  margin: 0;
  list-style-type: none;
}

你可能会冲我大喊,说我可以把它们放在我的 CSS 重置中。 我希望我能做到,但我不想这样做,我马上告诉你为什么。

用户代理将值设置为列表中的这些属性,目的是使列表更易读。 这些是 chromium 浏览器中 <ul> 元素的默认样式

ul {
  list-style-type: disc;
  margin-block-start: 1em;
  margin-block-end: 1em;
  margin-inline-start: 0px;
  margin-inline-end: 0px;
  padding-inline-start: 40px;
}

所以,在不添加任何 HTML 类或 CSS 样式的情况下,我们可以免费获得这些。 这是一件好事,我不想失去它。 但我希望浏览器能够理解,当我向元素添加类时,我极有可能不需要该默认功能。

所以这里有一个快速解决方案来重置具有类的 <ul> 元素

ul[class] {
  padding: 0;
  margin: 0;
  list-style-type: none;
}

现在,除了向 <ul> 元素添加类时,我不会丢失默认样式。

问题

此解决方案存在问题。 想象一下,我们有一个列表,我们希望为它设置不同的 list-style-type,如下所示

ul[class] {
  padding: 0;
  margin: 0;
  list-style-type: none;
}

.list {
  list-style-type: square;
}

这不起作用,因为 ul[class] 具有更高的特异性。 这就是我们的解决方案失败的地方。

我们可以为选择器的特异性添加更多权重

ul.list {
  list-style-type: square; /* Specificity: 0, 1, 1 */
}

/* or */

.sidebar .list {
  list-style-type: square; /* Specificity: 0, 2, 0 */
}

如果您不介意为选择器添加更多权重,那么就可以开始了。 但我个人不赞成这样做。 例如,由于关注点分离原则,我不想在大多数情况下将元素名称放在我的 CSS 中。 或者,如果您遵循 BEM 方法论,问题一定会出现,因为这与它冲突。

那我们该怎么办呢?

解决方案

几个月前,我了解了一些热门选择器,包括 :is():where()。 这两个功能性伪选择器的一点是,它们可以改变特异性,赋予我们消除或增加特异性的能力。

:where() 的关键是它始终具有 0 特异性。 所以我们可以很容易地像这样消除我们的问题

:where(ul[class]) {
  list-style: none;
}

.list {
  list-style: square; /* Now this works like a charm! */
}

凭借此选择器的强大功能,库可以为我们提供没有特异性的样式。 因此,当我们作为作者编写 CSS 时,将不会有任何特异性来竞争。

演示

在以下演示中,您可以删除 :where() 以查看我们在实际操作中讨论的内容