.btn.btn 权重高于 .btn 是因 CSS 权重规则中每个类选择器独立计分,.btn.btn 的 c 位为 2,权重 (0,0,2,0),与 .btn.primary 相同,但仅当 class 属性真实重复时生效。

.btn.btn 确实比 .btn 权重高,但这不是“重复生效”的魔法,而是 CSS 权重计算规则的机械结果——每个类选择器单独计 1 分,写两遍就多加 1 点。
权重计算中,每个 .class 都算独立的类选择器
浏览器按四位数 (a, b, c, d) 计算权重:c 位代表“类选择器、属性选择器、伪类”的数量。所以:
-
.btn→c = 1,权重为(0, 0, 1, 0) -
.btn.btn→ 两个类选择器 →c = 2,权重为(0, 0, 2, 0)
它和 .btn.primary 权重相同,都是 (0, 0, 2, 0);也和 button.btn((0, 0, 1, 1))不同——后者靠元素选择器补位,但总分仍低于前者。
只对同一元素上的重复类名有效
这个机制只在 HTML 元素的 class 属性里真实写了两次时才触发:
立即学习“前端免费学习笔记(深入)”;
-
<button class="primary primary">✔️ 触发权重叠加 -
<button class="primary">+ 另一条规则.primary或.btn.primary❌ 不叠加,权重按各自选择器结构单独算
换句话说:CSS 选择器不“数你写了几个 .primary”,它只看你匹配到的元素上,class 属性值里是否真有重复字符串,并且该选择器是否完整匹配整个属性值(用空格分隔)。
现代项目里靠重复类名提权,往往暴露了结构问题
真正需要提权时,更可靠的做法是换路径,而不是堆写法:
- 用父容器限定:
.card .title比.title.title更清晰、可维护 - 加属性选择器:
button.btn或[data-role="submit"],天然升一级 - BEM 类名本身已含语义层级,
.button.button--large是规范要求,不是权宜之计 -
!important仅用于覆盖第三方库内联样式或主题切换等极少数场景
重复类名容易被构建工具误判为冗余而删除,也会让可访问性检测工具报 duplicate-class 警告——它不破坏功能,但干扰真实问题定位。
真正该盯住的,从来不是“怎么多加 1 点权重”,而是“为什么需要抢权重”:样式表引入顺序不合理?用了通配符重置(如 * { all: unset })?目标元素其实在 shadow DOM 里?这些才是权重冲突背后更常被忽略的根因。


















