
一、简述
CSS中有两个重要的基础规则,一个是级联(Cascading),一个是继承(Inheritance)。
继承指的是类似 color, font-family, visibility 等属性父元素设置,子元素会被继承的特性。
那级联指的是什么呢?
在 JS 中,方法的连续执行可以称为级联。
例如:
var fn = {
a: function () {
return this;
},
b: function () {
return this;
}
};
// 级联调用
fn.a().b();
CSS中的级联与上面神似。
当我们应用某个 CSS 样式的时候,你可以理解为有很多的前后应用方法。
fn.styleA().styleB().styleC()...
最终该应用哪个 CSS 样式,就是基于这些级联规则来的。
按照目前的 CSS 规范的描述,CSS 级联的优先级是这样的(按序号递减):
- transition 过渡声明;
- 设置了 !important 的浏览器内置样式;
- 设置了 !important 的用户设置的样式;
- 前端开发者在 @layer 规则中设置的包含 !important 的样式;
- 前端开发者平常设置的包含 !important的样式;
- animation 动画声明;
- 前端开发者设置的 CSS 样式。
- @layer 规则中的样式;
- 用户在浏览器中设置的样式;
- 浏览器自身内置的样式;
晕了晕了!
都什么跟什么,不急,且听我娓娓道来。
二、级联规则详解
1. 先不用管 !important
为了方便我们理解,我们可以先不用关心 !important 对级联优先级的影响。
因此,理论上的级联优先级是:
transition > animation > 常规CSS > @layer规则 > 用户设置 > 浏览器内置
2. 也不用管 transition 和 animation
transition 和 animation 声明下的级联规则大家也可以不用太关心,为什么呢?
主要是浏览器的真实表现和规范中定义的并不一样。
例如设置了 !important 属性的 CSS 应该优先级比 animation 高,但是,在 IE,IE Edge,Chrome 以及 Safari 浏览器下,动画执行的优先级是最高的,超越 !important。
《CSS新世界》中有专门介绍过,demo见这里。

至于 transition 的最高优先级更是无从谈起,我反复测试,都是普通 CSS 属性的表现。
所以,我们应该关心的级联优先级其实就这么几个:
常规CSS > @layer规则 > 用户设置 > 浏览器内置
3. 常见且重要的四种级联规则
常规CSS
所谓常规 CSS,指的是开发人员在 CSS 文件,<style> 元素,或使用 HTML style 内联属性设置的 CSS样式。

@layer规则
CSS @layer 规则是最近现代浏览器纷纷支持了一个极具颠覆性的新特性,兼容性如下图所示:

这个规则可以让其中设置的所有 CSS 的优先级降低,特别适合在引入某个模块的时候使用,可以优先避免他人的代码因为优先级原因影响自己的代码。
例如:
<button id="button">我是按钮</button>
button {
color: red;
}
@layer {
#button {
color: green;
}
}
此时虽然 ID 选择器的优先级很高,但由于在 @layer 规则中,优先级没有外面的标签选择器 button 高,因此按钮是红色:

关于 @layer 规则我会在下一篇文章中详细介绍。
用户设置
用户设置的 CSS 多指用户安装插件等工具所设置的 CSS(称为"注入的样式表"),比方说 Adblock 等插件对页面元素隐藏的 CSS 就属于这一类。
以及,我个人认为(实际并不准确),用户通过浏览器自身的设置改变浏览器的主题背景,字号或字体等也可以归为这一类。

浏览器内置
官方说法叫做用户代理样式,其实就是浏览器内置的样式。
这个大家都见得比较多,很多 HTML 元素会内置样式,常见的如 <body>, <p> 等元素的 margin 外间距,<input>、<button>等元素的边框和背景色样式等。

上面这四种类型就是目前主要的级联规则。
每一种级联规则的优先级都是超越下一个级联规则的,除非使用 !important 进行逆袭,否则是无法重置。
4. 逆向运作的 important 标识符
!important 有个很有意思的特性,那就是原本级联水平高的CSS声明应用了!important后,其优先级反而低,而原本级联水平低的 CSS 声明应用了 !important 后,CSS 计算的优先级反而高。
例如,用户代理 CSS(浏览器内置 CSS)在级联规则中处于底层,但是,一旦这些属性值的后面增加了 !important。
不得了!绝地大翻身,超级大逆袭,优先级直接升到超级霸主的地位,完全不可撼动!
如果我们平时比较敏感,就会看到浏览器内置的不少 CSS 后面设置了 !important。
跟大家讲,这些 CSS 样式你就不要白日做梦,说的是我去重置他!
瞎子点灯白费蜡,一点毛用都没有!

同样的,Chrome 有很多广告拦截插件,其会通过注入 CSS 的方式让广告容器隐藏,其相关代码会是这样的:

这些里的 display: none 隐藏开发人员是无论如何也无法重置的,被级联规则给限制了。
三、完整的样式优先级
一个 CSS 样式是否生效,其优先级是由下面这三句话决定的。
这三句话很重要,大家可以拿小本本记一下。
1. 继承是最底层,低于所有的级联规则。
2. 级联规则无法跨越,除非使用 !important 逆袭。
3. 同一级联规则内的优先级按照选择器权重和先后顺序决定。
用一张图表示就是:

本人使用figma辛苦绘制的。
如果有人因为某些原因需要原始高清无水印大图(2592*2624),可以加我微信 zhangxinxu-job 五元购买之。
四、结语啦~
扎实的基础知识有助于我们看到某些看似普通但不解的背后现象的原因。
例如,为何浏览器内置的输入框样式我们可以轻松重置,但是设置了 !important 的浏览器内置样式为何重置无效呢?
如果你了解 CSS 中的级联规则,就能一下子搞清楚其中的门道了。
而平常我们开发,都是在"开发者样式设置"这个级联规则下进行的,基本上全都在这个小世界中运行,因此,大家都安好,不懂级联规则也没什么大不了。
但是,随着 @layer 规则的出现,相当于在"开发者样式设置"这个级联规则内又开篇了一个新的级联规则,此时再不了解这个基础知识,学习和理解恐怕就不一定跟得上了。
所以,无论哪门语言的学习,基础和体系都是极为重要的。
好啦,就说这么多,希望本文的内容可以帮助到大家的学习。
如果觉得内容不错,欢迎分享哦,比心!
(本篇完)
51工具盒子