CSS新特性@layer
CSS里的C,指的是Cascading,也就是层叠,只有了解层叠是怎么解决样式规则冲突,我们才能准确快速地设置某个元素的样式。
层叠的规则是按照“样式表来源”、“选择器优先级”、“源码顺序”来考虑的,下图展示了一个判定流程:
但是页面一复杂,组件一多,样式管理起来还是很费劲,很多时候还是得用自己不想用的一些优先级权重高的选择器去覆写样式,比如ID或者 !important,所以CSS新出一个 @layer 特性,能让样式得到更好的管理和控制。
语法
大家用过ps的话,很好理解 @layer ,它就像ps里的图层一样,可以对ps图层进行排序,上面的图层有更高的优先级,@layer 的一个重要作用,就是可以提前定义好“级联层”的优先级:
@layer bootstrap,base,application;
@import url(bootstrap.css) layer(bootstrap);
@layer base {
body {
/* ... */
}
}
在上面的代码中,我们先是用@layer bootstrap,base,application
声明了三个layer,这三个layer的优先级从低到高依次为:bootstrap > base > application,bootstrap组件的样式优先级最低,方便我们修改部分组件样式,application层的优先又高于base,能对内容区块进行更细粒度的样式控制,这样就在样式设计之初,进行了一个管理规划。
从上面的代码中,我们可以看到三种创建 CSS @layer 的方法:
- 直接创建一个块级的 @layer 规则:
@layer base {
body {
/* ... */
}
}
- 通过 @import 来创建层:
@import url(bootstrap.css) layer(bootstrap);
- 先创建带命名的layer,但不先编写样式代码,像代码中的
application
层就是如此,后面要编写application
层的时候,再去该层中编写样式:
@layer application;
/* */
/* */
@layer application{
a{
color:red;
}
}
我们通过一个实例来看一下layer间的优先级:
HTML
<div class="item">这段文字是<em>红色</em></div>
CSS
@layer base,application;
@layer application {
.item {
color: red;
}
}
@layer base {
.item {
color: green;
border: 5px solid green;
font-size: 1.5em;
padding: 0.5em;
}
}
@layer application
的样式规则虽然写在@layer base
之前,但在定义layer时,application在base之后,优先级更高,所以application定义的color属性,会生效:
layer间的优先级,比选择器优先级具有更高的权重,比如刚刚的示例中,我们修改下样式代码:
@layer base,application;
@layer application {
em {
color: red;
}
}
@layer base {
.item em {
color: green;
}
}
从选择器优先级的角度来看,.item em
是比em
这个标签选择器优先级高的,但是从layer来看,application优先级高于base,所以<em>
的颜色最后是红色。
非@layer层与@layer层的优先级
当然,我们还得考虑到,没有被 @layer 包裹的样式,它的优先级和被 @layer 包裹的样式,哪个优先级更高?
试验一下:
HTML
<body>
I'm using @layers.
</body>
CSS
body {
background-color: bisque;
}
@layer A {
body {
background-color: red;
color: black;
}
}
@layer B {
body {
color: blue;
background-color: green;
}
}
网页效果为:
可以看到:非 @layer 包裹的样式,就算写在其他layer之前,也拥有比 @layer 包裹样式更高的优先级。
@layer 还是一个实验中的功能,我是在 Chrome 100 版本里使用的该特性,Chrome 99、Edge 99、Firefox 97以及 Safari 15.4之后的版本,目前都支持该特性。
匿名层
匿名层指的是不声明layer名的级联层,它在级联层中的优先级,取决于layer声明次序:
@layer A {
body {
background-color: green;
}
}
@layer {
body {
background-color: red;
}
}
@layer B {
body {
background-color: bisque;
}
}
优先级从高到低为: B > 匿名 > A,所以最后生效的body背景色为bisque
。
嵌套层
CSS原生的嵌套虽然还没实装,但是草案已经出来蛮长的时间了,@layer 也是支持嵌套的:
@layer A {
@layer B{
...
}
}
等价于:
@layer A.B {
...
}
这里要注意一下, A 的优先级是高于 A.B 的:
@layer A {
div {
background: blue;
}
@layer B {
div {
background: red;
}
}
}
body 最终背景色为 blue ,这个也好理解,假设没有 A 这层 layer 包裹,那么实际上就是 layer 和非 layer 的优先级较量,非layer的更高,对吧。
而如果存在 layer 多级嵌套的话,优先级高的 layer ,无论是否有嵌套,都比优先级低的 layer 高,比如:
HTML
<div>I'm using @layers.</div>
CSS
div {
padding: 20px;
width: 300px;
height: 50px;
}
@layer A {
div {
background: blue;
}
@layer B {
div {
background: red;
}
}
}
@layer C {
div {
background: bisque;
}
@layer D {
div {
background: green;
}
}
}
优先级从高到低:@layer C > @layer C.D > @layer A > @layerA.B,所以最后div的背景色为:
总之,@layer 还是蛮好用的,希望能尽快在业务代码里面用到吧。