层叠顺序由层叠起源、优先级和源顺序共同决定,并非“后来者居上”;内联样式因层叠起源更高而看似“无敌”,同选择器内重复声明以最后出现的为准。

层叠顺序不是“后来者居上”
很多人以为后面写的 CSS 规则一定覆盖前面的,其实不是。浏览器判断哪条样式生效,靠的是「层叠顺序(cascade origin) + 优先级(specificity) + 源顺序(source order)」三者共同决定,其中 specificity(选择器权重)经常压倒后写的规则。
-
!important会提升声明的层叠层级,但只对同源样式生效;内联样式中的!important仍可能被更高层(如用户样式表)覆盖 - 浏览器默认样式(user agent stylesheet)优先级最低,作者样式(你写的 CSS)中,
style属性 > ID 选择器 > 类/属性/伪类 > 元素/伪元素 - 两个相同 specificity 的规则,才看谁写在后面;比如
.btn和[type="button"]权重都是 0,1,0,这时后定义的胜出
内联样式为什么看起来“无敌”
因为它的层叠起源(origin)属于“inline styles”,天然高于外部样式表和 <style></style> 块。它不靠 specificity 赢,而是靠 cascade 层级更高。
- JS 动态设置
element.style.color = "red",等价于写了style="color: red",直接跳过选择器匹配流程 - 用
getComputedStyle()能读到最终生效值,但element.style.color只返回内联值,哪怕被其他规则覆盖了也显示空字符串 - 想用 JS 覆盖内联样式?得用
element.style.setProperty("color", "blue", "important"),否则普通 set 不敌已有的内联声明
同一选择器里多个声明的覆盖逻辑
同一个 CSS 规则块内部,重复声明同名属性时,**最后出现的那个生效**,且不涉及 specificity 或 origin 判断——这是最简单的覆盖场景。
-
color: red; color: blue;→ 最终是blue - 但
color: red !important; color: blue;→ 还是red,因为!important在本规则内就已锁定该声明 - 注意:CSS 自定义属性(
--main-color)也遵循此规则,但它们只是变量,不直接渲染,真正起作用的是引用它们的地方
@import 和 link 加载顺序影响层叠吗
影响,而且容易被忽略。@import 是 CSS 内部语句,它引入的样式表会被当作“当前样式表的一部分”,其规则插入位置取决于 @import 出现的位置,而不是文件物理加载完成时间。
立即学习“前端免费学习笔记(深入)”;
- 写在
<style></style>开头的@import url("a.css");,相当于把 a.css 的全部内容复制粘贴到此处;它比后面写的本地规则权重低(因 source order 靠前) - 多个
@import之间按书写顺序层叠,但所有@import都低于后续同文件中的普通规则 - 现代项目尽量避免
@import,尤其在 CSS 文件中嵌套 import,会导致阻塞渲染、无法并行加载,还让开发者误判层叠关系
真正难的不是记住规则,而是当一个颜色没变、一个 margin 没生效时,你得立刻想到打开开发者工具的 computed 标签页,看那条被划掉的样式旁边写着 “crossed out by …”,然后点进去找源头——那里往往藏着一个没注意到的 :is()、一个继承来的 color,或者一个从 shadow DOM 外透进来的变量。










