先记住这个答案
当两条规则来源相同、选择器优先级完全相等且都作用于同一元素的同一属性时,CSS 按来源顺序裁决:后出现的声明覆盖先前的。但这只在同一层叠层内成立。如果使用了 @layer,层的先后顺序先决定胜负,后声明的层整体高于先前的层,与层内规则的书写位置无关。另外,未放入任何层的样式默认优先级高于所有命名层中的普通样式。因此判断顺序是:先比层,再比优先级,最后才比来源顺序。
- 同层同优先级,后书写的规则胜出
- 层顺序先于层内来源顺序生效
- 无层普通样式高于命名层内样式
来源顺序与层叠层的裁决次序
层叠机制解决冲突时按固定次序比较多个维度。在来源相同、均为普通声明的前提下,先比较规则所在的层叠层:后声明的层整体优先级更高。只有两条规则落在同一层内,才进入选择器优先级比较;优先级也相等时,才轮到来源顺序——样式表或文档中后书写的那条声明生效,覆盖先前同属性的值。
因此「后写的赢」是有前提的结论,而非普遍规律。一旦项目引入 @layer,规则在文件中的物理位置不再是决定性因素。例如把基础样式放进先声明的 base 层,把覆盖样式放进后声明的 overrides 层,即使 base 层里某条规则写在文件末尾,它仍输给 overrides 层中位置更早的等优先级规则。
/* 无层:同优先级,后写的胜出,文字为蓝色 */
p { color: red; }
p { color: blue; }
/* 有层:层顺序决定胜负,文字为绿色 */
@layer first, second;
@layer second {
p { color: green; }
}
@layer first {
/* 虽然写在文件最后,但 first 层先声明,输给 second 层 */
p { color: orange; }
}适用于支持层叠层的现代浏览器。第一段两条规则同层同优先级,蓝色生效;第二段 first 层先声明,其规则即使位置更靠后也输给 second 层。
第三方组件库与业务覆盖样式的冲突
一个项目引入第三方组件库的按钮样式 .btn { padding: 4px },业务代码自己写 .btn { padding: 12px }。约束是:两者选择器相同、优先级相等,且业务样式表通过 <link> 在组件库之后加载。依据来源顺序规则,后加载的业务样式胜出,按钮内边距为 12px,这正是覆盖第三方样式最常用的低成本手段。
后来团队为管理覆盖关系把组件库样式包进 @layer vendor,业务样式未入层,此时由于未入层的普通样式默认高于所有命名层,按钮内边距仍为 12px,覆盖不会失效。真正会失效的情形是:业务样式也被引入层,且所在层由于声明顺序早于 vendor 而被判为优先级较低,这时组件库的层内规则才会胜出,按钮内边距变回 4px。修复方式是把业务覆盖放进最后声明的层,或继续保持业务样式不入层,以利用无层样式天然高于层内样式的特性。
来源顺序失效的常见条件
来源顺序只在优先级相等时才被触达。若先出现的规则选择器优先级更高,例如 #id 对 .class,后写的低优先级规则永远无法靠位置翻盘。同样,来源不同的规则(作者样式与用户代理样式)不进入同一比较池。媒体查询、伪类状态也不会改变顺序规则,:hover 规则与常态规则各自独立层叠。
另一个失效点是样式表的加载次序不等于书写直觉:通过 @import、多个 <link> 或打包工具合并后的最终顺序才有效,源代码里的书写位置可能被构建工具重排。对应处理是用浏览器开发者工具的样式面板查看实际生效的规则及其被划掉的声明,确认最终级联顺序;代价是构建产物顺序不稳定时,应改用层叠层显式声明覆盖关系,而不是依赖脆弱的物理顺序。
容易答错的地方
- 后写的规则一定生效
- 来源顺序是同优先级下的最后裁决步骤。若先前的规则选择器优先级更高,或两者分属不同层叠层且先写的层更靠后声明,后书写的规则仍会输掉冲突。
- @layer 只是组织代码的注释
- 层叠层实际参与优先级计算。放入层的普通样式优先级低于未入层样式,且层与层之间按声明顺序分胜负,层内规则的书写位置无法跨越层的边界取胜。
面试官还会怎么问?
未放入 @layer 的样式与层内样式冲突谁赢?
普通(非 important)声明中,未入层的样式优先级高于所有命名层内的样式。所以把第三方库包进层、自己的覆盖样式留在层外,是常见的覆盖策略。
多个 @layer 语句顺序如何确定?
层的顺序由层名首次出现的位置决定,既可用 @layer a, b, c; 一次性声明,也按各层首次定义的自然顺序排列,后续同名层块只追加规则不改顺序。
同一规则块内多条相同属性声明谁生效?
同一声明块内出现重复属性时,同样是后出现的合法声明生效。可利用这一点写降级:先写旧值再写新值,不支持新值的浏览器会忽略后者而保留前者。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。