id选择器优先级永远高于多类名组合,因其权重为(0,1,0,0),而十个类选择器仅得(0,0,10,0),四元组从左逐位比较,b位1>0直接胜出;id应慎用,因违背组件化、导致复用困难与js耦合。

ID选择器的优先级永远高于多类名组合
哪怕你写十个类名连在一起,比如 .btn.primary.large.disabled.hovered.active.focus-visible.urgent,它的权重(0,0,1,0)×10 仍是(0,0,10,0),而单个 #submit 的权重是(0,1,0,0)。CSS 优先级计算不看“长度”或“数量”,只看四元组:内联样式 > ID > 类/属性/伪类 > 标签/伪元素。ID 的千位(1)直接碾压类名的百位(最多加到 999 也没用)。
#id.class 这种混合写法的权重怎么算
这是常见误解点:很多人以为加个类名能“增强”ID 的效果,其实它只是缩小了匹配范围,权重不变。例如 #nav .menu-item 是后代选择器,权重为(0,1,1,0);而 #nav.menu-item(ID 和类在同一元素上)才是(0,1,1,0)——注意,这里类名没白加,但不是“叠加优先级”,而是“共同限定同一个元素”。关键区别:
-
#header.nav:匹配同时有id="header"和class="nav"的那个元素,权重(0,1,1,0) -
.header.nav:匹配任意同时含这两个类的元素,权重(0,0,2,0) -
#header .nav:匹配#header内部任意带class="nav"的后代,权重(0,1,0,1)
为什么你感觉“多类名有时赢了ID”
那基本不是优先级问题,而是以下几种情况之一:
- HTML里实际没写那个
id,或者拼错了,document.getElementById("xxx")返回null,样式根本没生效 - CSS文件加载顺序导致层叠覆盖:后声明的
#id规则会覆盖前面同权重的规则,但若前面是#id,后面是.a.b.c.d.e,后者绝不会胜出 - 用了
!important—— 它绕过所有优先级计算,但会破坏可维护性,且无法解决 JS 动态渲染时 ID 重复导致的document.getElementById只返回第一个的问题 - 浏览器 DevTools 显示“已删除线”的样式,其实是被更高优先级规则覆盖,而非“类名赢了”,要展开看 computed 样式来源
真正该关心的是:ID 在现代 CSS 工程中是否还该用
答案是:尽量不用。不是因为优先级太高难控制,而是因为 ID 天然违背组件化原则:
- ID 必须全局唯一,但组件可能被多次实例化,
id="modal-close"在两个弹窗里就冲突 - CSS Modules、Shadow DOM、
[data-*]属性选择器(如[data-component="button"])权重同级类(0,0,1,0),无唯一性约束 - JS 中用
getElementById获取元素,在 SSR 或 hydration 不一致时容易出错;改用querySelector(".js-modal-close")更健壮 - BEM 命名(如
.button--primary)或原子类(如bg-blue-500 text-white)天然规避权重博弈
优先级数字只是表象,真正卡住团队协作的,是 ID 强制的全局命名空间和隐式依赖。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











