CSS选择器世界(第2版)
上QQ阅读APP看书,第一时间看更新

2.2.1 @layer规则解决的问题

先讲解一下设计@layer的初衷。

我们在实际开发的时候,经常会使用第三方组件。每个产品通常都有自己的UI样式风格,当引入第三方组件的时候,往往需要对这些组件的UI进行重置,例如换肤、变色等。此时,我们的做法是使用优先级更高的选择器进行覆盖,例如第三方组件中某个按钮的选择器是:

.container .some-button { height: 30px; }

当需要重置的时候,可能就会使用类似于下面的选择器,通过增加选择器复杂度的方式进行重置。

.reset .container .some-button { height: 40px; }

这就会使我们的CSS代码变得很臃肿,维护成本上升,同时过于复杂的选择器也使CSS渲染的性能不是很好。

又如这个困扰我很久的例子,对于链接元素的CSS reset,有一种非常好的方法是使用:any-link伪类,代码示意如下:

:any-link { color: darkblue; }
:any-link:hover { color: blue; }

其语义明确,匹配精准,且无须担心:visited伪类的干扰,可以参见10.2节讲解的超链接伪类。

然而,这个伪类却很少有人使用,其原因只有一个,那就是伪类的优先级比较高,不太适合作为CSS reset使用,因为一旦设置这个伪类,某个<a>元素按钮想要被重置颜色,所需的选择器成本就会很高,提升了整个项目的选择器复杂度。

而有了@layer规则,上面这些问题就迎刃而解了。我们只要将希望获得低优先级的CSS代码放在@layer规则中,就无须再担心选择器优先级过高的问题,因为@layer规则的级联层级比常规的CSS代码的级联层级低。

参见这里的CSS代码示意:

@layer {
  .container .some-button { height: 30px; }
  :any-link { color: darkblue; }
  :any-link:hover { color: blue; }
}
/* 业务代码 */
.some-button { height: 40px; }
a { color: deepskyblue; }

此时相关的CSS代码在浏览器的优先级层级关系如图2-5和图2-6所示。

图2-5 按钮的单类名优先级更高

图2-6 <a>元素优先级高于:any-link伪类

从图2-5可以看出,虽然业务代码中的按钮选择器只有一个类名.some-button,其优先级低于.container.some-button这两个类名,但是由于代码所在的级联层级更高,因此,还是重置了30px

从图2-6可以看出,链接的颜色最终按照a标签选择器渲染了,再也不用担心:any-link伪类作为CSS reset代码会影响业务代码中<a>元素的样式设置了。

眼见为实,读者可以输入https://demo.cssworld.cn/selector2/2/2-1.php或者扫描下面的二维码查看对应的效果。

这就是@layer规则的作用,可以让CSS代码的级联层级降低,从而确保主业务的CSS代码不受第三方组件的CSS代码的影响。