后写必胜是css层叠规范明确规则:当选择器权重完全相等时,源码顺序决定覆盖结果,后声明的样式生效。典型场景包括同权重类组合、相同结构的复合选择器及外部与内部样式表中重复定义的规则。

因为浏览器按样式表的源顺序(source order)逐条解析规则,当多个规则优先级完全相等时,后出现的那条直接覆盖前面的——这不是“浏览器随机选”,而是明确写在 CSS 规范里的层叠(cascading)行为。
浏览器解析 CSS 时是线性读取的
CSS 不是“一次性算出所有权重再比大小”,而是边解析边构建样式映射。遇到一个元素,浏览器会收集所有匹配该元素的选择器声明,按它们在样式表中出现的顺序排成一个列表;然后从头到尾扫描这个列表,相同优先级的声明,后面的自然会把前面的同名属性值冲掉。
这和 JavaScript 变量赋值类似:let color = 'red'; color = 'blue'; 最终就是 blue,不是因为 blue 更“高级”,只是它后执行。
优先级相等的典型场景有哪些?
这些情况都属于权重四元组 (a,b,c,d) 完全一致:
- 同一类选择器重复使用,比如
.btn .primary和.btn .cta(都是 0,0,2,0) - 不同类但权重凑巧相同,比如
#nav a:hover(0,1,1,1) vs.menu .link.active(0,0,3,1)——注意:后者类选择器共 3 个,3×10 = 30,前者 ID(100) + 伪类(10) + 元素(1) = 111,其实不等;真正相等的例子是.header .logo img(0,0,2,1)和.sidebar .avatar img(0,0,2,1) - 外部样式表与内部样式表里写了完全一样的选择器(比如都用
p.intro),且都未被!important干扰
为什么不能靠“多写几个类”来强行压过 ID 选择器?
很多人试过 .a.b.c.d.e.f.g.h 去覆盖 #main,结果失败了——因为权重不是十进制加法,而是独立位存储。ID 选择器占高位字节,哪怕你写 20 个类,也只影响低一阶的字节,永远无法越过 b 位去干扰 a 或 b 的计数。
比如 #app 是 (0,1,0,0),而 .x.x.x.x.x.x.x.x.x.x(10 个类)仍是 (0,0,10,0);比较时先看 b:1 > 0,直接胜出,后面根本不会比 c。
调试时怎么一眼看出谁赢了?
打开 Chrome DevTools → Elements 面板 → 选中目标元素 → 右侧 Style 标签页:
- 所有被划掉的属性,说明它被同优先级但更靠后的规则覆盖了
- 鼠标悬停在某个选择器上,DevTools 会显示它的具体权重,格式如
0,0,2,1 - 如果某条规则带
!important,它会单独标记,且权重显示为∞(实际是绕过四元组比较)
真正容易被忽略的是:内联样式(style 属性)的 a 位为 1,它天然碾压所有外部或内部样式表里的任何选择器,哪怕你写了 #root #app .deep .nested div,也打不过一个简单的 style="color:red"。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











