学习 CSS At Rules 级联层 — @layer
什么是 CSS 级联
The cascade takes an unordered list of declared values for a given property on a given element, sorts them by their declaration’s precedence as determined below, and outputs a single cascaded value. ...
The cascade sorts declarations according to the following criteria, in descending order of precedence: 1.Transition declarations 2.Important user agent declarations 3.Important user declarations 4.Important author declarations 5.Animation declarations 6.Normal author declarations 7.Normal user declarations 8.Normal user agent declarations
官方定义
CSS 级联获取给定元素上给定属性声明值的无序列表,并将其按照下面的声明优先级对它们进行排序,并输出单个级联值。
- 过渡声明
- 重要用户代理声明
(浏览器默认样式 + !important)
- 重要用户声明
(浏览器用户样式 + !important)
- 重要作者声明
(开发者编写样式 + !important)
- 动画声明
- 普通作者声明
(开发者编写样式)
- 普通用户声明
(浏览器用户样式)
- 普通用户代理声明
(浏览器默认样式)
相关说明
-
其中
Transition
和Animation
声明的级联规则大家可以不用太关心,一是实际开发中这两类的级联规则很少会跟其他级联规则发生冲突,另一个原因是浏览器的真实表现和规范中定义的不一样 (例:Animation
实际呈现的级联是在 !important 之上)。 -
上述 CSS 优先级中
Author(开发者样式)
部分可以进一步分类,如下图:
什么是 CSS 级联层
In the same way that cascade origins provide a balance of power between user and author styles, cascade layers provide a structured way to organize and balance concerns within a single origin. Rules within a single cascade layer cascade together, without interleaving with style rules outside the layer.
官方定义
正如级联源提供用户和作者风格之间的力量平衡一样,级联层提供了一种结构化的方式来组织和平衡单个源中的关注点。单个级联层内的规则级联在一起,而不与层外的样式规则交错。
相关说明
如何理解: 级联层 @layer
可以将某些CSS文件或某些CSS代码块建立一个层级,同层级内的规则将级联在一起。它有点像 PS
中的图层概念,有上下层级之分,上层内容呈现覆盖在下层内容之上。而且在一个图层中的操作 (创建选区,复制、移动、剪切),不会影响其他图层原内容。级联层 @layer
亦是如此,不同的级联层的规则不会交错干涉。但在优先级权重上,上层级联规则覆盖低层级联规则。
应用场景: 在实际前端项目中,我们往往需要引用第三方组件库 (比如 Ant Design Vue
、Vant
) 进行快速开发或迭代。但有时候根据实际业务需求,这些组件虽然功能是我们需要的,但是 UI样式
却和产品风格不一致,则需要重置某些样式或更换主题风格。例如:
<!-- Card 组件内 -->
<div class="card-container">
<div class="card-header">
<div class="card-title">Card Title</div>
</card-header>
<div class="card-content">
<slot></slot>
</div>
</div>
/* card.css 文件内 */
/* 定义了 Card title 字体颜色为黑色 */
.card-container .card-header .card-title {
color: #303133;
}
重置 Card 组件 title 字体颜色为红色 (#F34D4D
)
-
没有使用
级联层 @layer
时, 通过增加CSS 选择器
或!important
覆盖原组件里的UI样式
。这就需要我们了解组件内部样式级联,当然这并不易于后续UI样式
维护。/* parent.css 文件内 */ .card-container > .card-header > .card-title { color: #F34D4D; } /* global.css 引入样式文件 */ @import url(./parent.css); @import url(./card.css);
-
当使用
级联层 @layer
时,我们可以在引用样式的时候,去定义不同的layer
,并指定layer
之间的顺序,轻而易举实现CSS优先级
的重置,从而覆盖原组件里的UI样式
。/* parent.css 文件内 */ .card-container .card-title { color: #F34D4D; } /* global.css 引入样式文件 */ @layer card, parent; /* 指定 layer 顺序 */ @import url(./parent.css) layer(parent); /* 指定 layer 名称为 parent */ @import url(./card.css) layer(card); /* 指定 layer 名称为 card */
根据 CSS 优先级权重如下 (越前面权重越大)
inline-style + !important
first @layer + !important
... @layer + !important
last @layer + !important
no @layer + !important
inline-style
no @layer
last @layer
--- (parent.css)... @layer
first @layer
--- (card.css)
学习 CSS 级联层 @layer
语法定义
-
在 @layer 语法中,定义 块级级联层
/* 创建一个匿名的级联层,缺点: 无法后续追加样式 */ @layer { .padding { padding: 0; } } /* 创建一个名为 common 的级联层,但未分配任何样式。可以后续追加样式 */ @layer theme, layout, utilities; /* 多个,相当指定了顺序 */ @layer common; /* 创建一个名为 reset 的级联层,并分配样式 */ @layer reset { .padding { padding: 0; } } /* 允许创建嵌套的级联层,下面两种创建方式等价 */ @layer reset { @layer normal { .padding { padding: 0; } } } @layer reset.normal { .padding { padding: 0; } } /* 在媒体查询内使用 @layer 时,如果屏幕尺寸更改,则会重新计算图层顺序 */ @media (min-width: 30em) { @layer layout { .title { font-size: x-large; } } }
-
在 @import 语法中,定义被引入样式的级联层
/* 为被引入的样式表分配一个匿名级联层 */ @import url(reset.css) layer; /* 为被引入的样式表分配一个级联层,命名为 reset */ @import url(reset.css) layer(reset);
-
在 <link> 语法中,定义被引入样式的级联层 (暂不支持,尚在计划阶段)
<!-- 为被引入的样式表分配一个级联层,命名为 reset --> <link rel="stylesheet" layer="reset" href="reset.css"> <!-- 为被引入的样式表分配一个级联层,命名为 reset --> <link rel="stylesheet" layer="reset" media="supports(at-rule(@layer))" href="reset.css">
级联层顺序
-
默认情况下 (即未显示指定顺序),则级联层按照书写顺序定义排序,其中如果存在重复的同一命名级联层,则只会定义第一次的顺序
/* 未使用级联层 */ div { color: white; } /* 匿名级联层 - No.1 */ @layer { div { color: blue; } } /* 命名A1级联层 - No.2 */ @layer A1 { div { color: orange; } } /* 命名A2级联层 - No.3 */ @layer A2 { div { color: green; } } /* 命名A1级联层 - No.2,因为之前已经定义 */ @layer a1 { div { color: gray; } } /* 匿名级联层 - No.4 */ @layer { div { color: red; } } /* 最终应用样式, 未使用级联层样式优先级最高 (未设定 !important) */ /* blue < orange < gray < green < red < white, 所以应用 color: white; */
-
显示指定级联层顺序时, 则会自动将 匿名级联层 排在后面。
/* 指定级联层顺序 */ @layer A2, A1; /* 未使用级联层 */ div { color: white; } /* 匿名级联层 - No.3 */ @layer { div { color: blue; } } /* 命名A1级联层 - No.2 */ @layer A1 { div { color: orange; } } /* 命名A2级联层 - No.1 */ @layer A2 { div { color: green; } } /* 命名A1级联层 - No.2,因为之前已经定义 */ @layer a1 { div { color: gray; } } /* 匿名级联层 - No.4 */ @layer { div { color: red; } } /* 最终应用样式, 未使用级联层样式优先级最高 (未设定 !important) */ /* green < orange < gray < blue < red < white, 所以应用 color: white; */
最佳实践:使用语句规则预先建立图层顺序, 例如
@layer reset common other;
级联层优先级
级联层中 CSS优先级权重分两种情况,no !important
和 使用 !important
截然不同。在上个小结 级联层顺序 中,我们已经梳理讲解了 no !important
的情况。还是上次例子,我们看下!important
情况:
/* 指定级联层顺序 */
@layer A2, A1;
/* 未使用级联层 */
div { color: white !important; }
/* 匿名级联层 - No.3 */
@layer { div { color: blue !important; } }
/* 命名A1级联层 - No.2 */
@layer A1 { div { color: orange !important; } }
/* 命名A2级联层 - No.1 */
@layer A2 { div { color: green !important; } }
/* 命名A1级联层 - No.2,因为之前已经定义 */
@layer a1 { div { color: gray !important; } }
/* 匿名级联层 - No.4 */
@layer { div { color: red !important; } }
/* 最终应用样式 */
/* green > orange > gray > blue > red > white, 所以应用 color: green; */
权重规则如下: (越前面权重越大)
inline-style + !important
first @layer + !important
... @layer + !important
last @layer + !important
no @layer + !important
inline-style
no @layer
last @layer
... @layer
first @layer
CSS选择器权重
在没有 @layer 或 同在一个 @layer 情况下,则看CSS选择器权重,来决定 CSS优先级
inline-style + !important
css + !important
inline-style
css 选择器
-
ID 选择器 #app { /* css code*/ }
-
类选择器、属性选择器、伪类选择器 div.container { /* css code*/ } div[id="app"] { /* css code*/ } div:hover { /* css code*/ }
-
标签选择器、伪元素选择器 div { /* css code*/ } div::before { /* css code*/ }
-
通配选择符、关系选择符
-
继承
-
例外规则:
:is
、:not
本身不参与CSS优先级权重的计算, 但是在确定选择器类型计数时,放置在伪类中选择器将作为普通选择器计数 (例 :is(.container)
或 :not(.container)
, 其中 .container
参与CSS优先级权重计算)。
:where(.container)
不仅 :where
本身不参与CSS优先级权重的计算, 就 .container
也不参与CSS优先级权重的计算,这也算是 :where
的一个特性。
浏览器兼容性
目前在主流浏览器环境中兼容性良好(🚧 IE
除外)
转载自:https://juejin.cn/post/7283688117013807164