使用where()的特殊性作为CSS重设的方法

79 阅读2分钟

我不知道你的情况,但我在我的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()](https://css-tricks.com/almanac/selectors/i/is/)[:where()](https://css-tricks.com/almanac/selectors/w/where/).这两个功能性伪选择器的一个特点是,它们可以改变特异性,让我们有能力使特异性失效或增加。

关于:where() ,关键是它总是有0的特殊性。因此,我们可以像这样非常容易地摆脱我们的问题。

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

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

借助这个选择器的力量,库可以给我们提供没有特定性的样式。因此,当我们作为作者编写CSS时,就不会有任何特异性可言了。