内联样式权重固定为(1,0,0,0),不可叠加且最高优先级;id选择器每出现一次b位加1;类/属性/伪类共用c位可累加;权重逐位比较,不求和;继承样式权重为(0,0,0,0)。

内联样式权重固定为 (1,0,0,0),且不可叠加
只要元素带 style 属性,它的权重就是最高档的 (1,0,0,0),不管后面跟多少个 ID 或类选择器,都压不住它。比如 <div id="box" class="active" style="color: red;">,哪怕你写 <code>#box.active:hover(权重 (0,1,2,1)),也改不了这个 color。
注意:style 属性本身不参与“选择器组合计算”,它不是靠数量堆出来的,而是独立档位。哪怕你用 JS 动态设置 element.style.color = 'blue',也等效于写了内联样式,权重不变。
#id 每出现一次,b 位加 1,空格或 > 不影响计数
ID 选择器只看数量,不看嵌套关系。例如 #nav #menu .item 中有两个 #,权重是 (0,2,1,0);而 div#main input[type="text"] 里只有一个 ID,所以是 (0,1,1,2)。
常见错误:以为 #header nav ul li a 因为“更深”所以权重更高——其实它没 ID,只有标签,权重只是 (0,0,0,5),远低于一个 .btn((0,0,1,0))。
- 多个 ID 连写(如
#a#b)在现代浏览器中无效,不被解析,别这么写 - CSS 预处理器(如 Sass)里嵌套生成的 ID 选择器,仍按实际输出的 CSS 字符串统计 ID 数量
类、属性、伪类共用 c 位,可累加但不跨类型进位
.nav、[data-id]、:hover、:nth-child(2) 全部算作 +1 到 c,没有优先级高低之分。所以 .btn[data-loading]:focus 是 (0,0,3,0),和 .btn.primary.large(三个类)权重一样。
容易混淆的点:
-
::before是伪元素,算d位(+1),不是c;而:before(单冒号)是旧写法,部分浏览器仍识别为伪类,但规范已废弃,建议统一用双冒号 -
:not(.disabled)整体不算额外权重,只看括号里的内容——.disabled贡献 1 个c,:not本身不加分 -
.list > li:first-child:其中.list(c=1)、li(d=1)、:first-child(c=1),总权重(0,0,2,1);>符号不占位
权重比较是逐位进行的,a > b > c > d,不存在“总和相等就平手”
浏览器不会把 (0,1,0,0) 和 (0,0,10,0) 加起来比大小。前者是 ID,后者是 10 个类,但 b=1 > c=10,所以 ID 选择器赢。这就是为什么 #app 能轻松干掉一整行 BEM 类名。
真正容易翻车的地方:
- 用
!important时,它不改变选择器权重,而是直接跳过权重比较阶段——但两个!important规则之间,依然要走正常权重比对 - 继承来的样式权重是
(0,0,0,0),哪怕父元素用了#root,子元素没写任何选择器,继承值也永远输给最朴素的div((0,0,0,1)) - 通配符
*、组合符+、~、>全部不贡献权重,但它们影响匹配范围,间接决定哪条规则能“参与竞争”











