ID选择器权重永远高于任意数量的类选择器组合,因其权重四元组(0,1,0,0)在ID位(b位)比较时直接胜出,后续类数量不参与比较。

ID选择器权重永远高于任意数量的类选择器组合,不存在“换算”关系——因为权重不是数值加法,而是四元组逐位比较。
为什么#header胜过.btn.primary.large.disabled.hovered
很多人误以为“十个类名 = 10×10 = 100”,刚好等于一个 ID 的 100,可以打平。但这是错的。CSS 权重本质是四元组 (a,b,c,d):内联、ID、类/伪类、元素。其中:
-
#header是(0,1,0,0) -
.btn.primary.large.disabled.hovered是(0,0,5,0)(5 个类,c=5)
比较时先看 b 位:1 > 0,直接终止,后面 c 位的 5 根本不参与比较。哪怕你写 50 个类,结果仍是 (0,0,50,0),依然输给 (0,1,0,0)。
#nav .menu-item 和 #nav.menu-item 权重差在哪
这是高频混淆点,关键在“是否作用于同一元素”:
-
#nav .menu-item:后代选择器,匹配#nav内部的任意.menu-item元素 → 权重(0,1,1,0)(1 个 ID + 1 个类) -
#nav.menu-item:交集选择器,匹配同时具有id="nav"和class="menu-item"的**同一个元素** → 权重也是(0,1,1,0)
二者权重相同,但行为完全不同:#nav .menu-item 可能匹配嵌套很深的子元素,而 #nav.menu-item 只匹配那个唯一元素。别指望加个类就能“升级”ID 的权重,它只是收紧了匹配条件。
实际开发中哪些情况会让你误以为“类赢了ID”
几乎从来不是权重问题,而是以下真实原因:
- HTML 中 ID 拼写错误或重复,
document.getElementById("xxx")返回null,样式压根没挂上 - CSS 文件加载顺序导致层叠覆盖:后声明的
#header规则会覆盖前面同权重的规则;但后声明的.header永远盖不过前面的#header - 用了
!important—— 它绕过所有权重计算,但会破坏可维护性,且无法解决 JS 动态渲染时 ID 重复的问题 - 你以为写了
#main,其实 DOM 里是id="Main"(大小写敏感)或data-id="main"(根本不是 ID 属性)
真正难的不是算出(0,1,0,0),而是放弃它
ID 的高权重是设计使然,不是鼓励你在 CSS 里滥用。现代工程实践中,#app 这类全局 ID 往往只留给 JS 入口定位用。一旦你用 #user-card 写样式,就锁死了复用可能——子组件想再用一次卡片结构?要么改 HTML,要么复制粘贴整套样式。更隐蔽的坑是:想覆盖它,你只能靠另一个 ID、内联样式或 !important,三者都比加个 .is-expanded class 更难维护。真正的解法往往不是“怎么赢过 ID”,而是删掉它,换成可组合、可继承、可 scoped 的 class 或属性选择器。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











