为什么CSS中ID选择器权重更高?其选择器权重原理是怎样的?
- 内容介绍
- 文章标签
- 相关推荐
本文共计911个文字,预计阅读时间需要4分钟。
由于CSS的权重要按照位权重来比较,ID选择器占据第二高位(位权为100),类选择器占据第三位(位权为10)。因此,在比较CSS权重时,ID选择器比类选择器更重要。
-
#nav .item权重是(0,1,1,0),而.nav .item .active div span是(0,0,3,5),前者胜出 - 嵌套再深、类名再多,
c和d再大也超不过b=1,就像百位数永远大于任何十位数 - 浏览器比较时根本不会算到第三位,看到
b=1 > b=0就直接停手
怎么快速算出一个选择器的权重?盯住 (a,b,c,d) 四位
别加总、别进位、别猜深度——只数四类符号:
-
a = 1当且仅当用了内联样式,否则为0 -
b= ID 选择器个数(#user、#modal各算 1,#app #main就是b=2) -
c= 所有类名(.btn)、属性([type])、伪类(:hover、:not(.active)中括号内部分)的总数 -
d= 标签名(div、p)和伪元素(::before)个数,组合符(、>、+)不计
例如:article#main .post[data-id]:hover::after → (0,1,3,2)(1 个 ID + 1 类 + 1 属性 + 1 伪类 = c=3;article + ::after = d=2)
为什么加了 class 还盖不过 ID?常见误判场景
开发者常以为 “写得更具体 = 更优先”,但 CSS 不看“看起来多不多”,只看四位是否高位占优。以下都是真实踩坑点:
立即学习“前端免费学习笔记(深入)”;
- 写
.modal .content span((0,0,2,3))想覆盖#user-name((0,1,0,0))→ 失败,b=1 > b=0直接碾压 - 用
div#header((0,1,0,1))和#header((0,1,0,0))权重相同,后写的才生效——加标签反而没用 -
:not(.active)本身不加权,但里面那个.active算 1 个c,容易漏数 - 继承来的样式权重是
(0,0,0,0),哪怕父级是#app,子元素写一行p { color: red; }((0,0,0,1))立刻生效
真要覆盖 ID 选择器?别赌顺序,换策略
靠写在后面、加更多类、或者深层嵌套,都不可靠。真正稳的方式只有两种:
- 用更高位:改用内联样式(
style="color: red"),但破坏可维护性 - 升一位:把目标选择器本身带上 ID,比如从
#user-name改成#user-name.edit-mode((0,1,1,0)),再写规则时自然高于原 ID - 慎用
!important:它能破局,但会污染后续所有覆盖逻辑,且无法对抗用户样式表里的!important
最易被忽略的一点:权重和 DOM 结构深度、选择器“长度”、文件引入顺序都无关。只看你写了几个 ID、几个类、几个标签——盯住 (a,b,c,d),一位一位比,问题就清楚了。
本文共计911个文字,预计阅读时间需要4分钟。
由于CSS的权重要按照位权重来比较,ID选择器占据第二高位(位权为100),类选择器占据第三位(位权为10)。因此,在比较CSS权重时,ID选择器比类选择器更重要。
-
#nav .item权重是(0,1,1,0),而.nav .item .active div span是(0,0,3,5),前者胜出 - 嵌套再深、类名再多,
c和d再大也超不过b=1,就像百位数永远大于任何十位数 - 浏览器比较时根本不会算到第三位,看到
b=1 > b=0就直接停手
怎么快速算出一个选择器的权重?盯住 (a,b,c,d) 四位
别加总、别进位、别猜深度——只数四类符号:
-
a = 1当且仅当用了内联样式,否则为0 -
b= ID 选择器个数(#user、#modal各算 1,#app #main就是b=2) -
c= 所有类名(.btn)、属性([type])、伪类(:hover、:not(.active)中括号内部分)的总数 -
d= 标签名(div、p)和伪元素(::before)个数,组合符(、>、+)不计
例如:article#main .post[data-id]:hover::after → (0,1,3,2)(1 个 ID + 1 类 + 1 属性 + 1 伪类 = c=3;article + ::after = d=2)
为什么加了 class 还盖不过 ID?常见误判场景
开发者常以为 “写得更具体 = 更优先”,但 CSS 不看“看起来多不多”,只看四位是否高位占优。以下都是真实踩坑点:
立即学习“前端免费学习笔记(深入)”;
- 写
.modal .content span((0,0,2,3))想覆盖#user-name((0,1,0,0))→ 失败,b=1 > b=0直接碾压 - 用
div#header((0,1,0,1))和#header((0,1,0,0))权重相同,后写的才生效——加标签反而没用 -
:not(.active)本身不加权,但里面那个.active算 1 个c,容易漏数 - 继承来的样式权重是
(0,0,0,0),哪怕父级是#app,子元素写一行p { color: red; }((0,0,0,1))立刻生效
真要覆盖 ID 选择器?别赌顺序,换策略
靠写在后面、加更多类、或者深层嵌套,都不可靠。真正稳的方式只有两种:
- 用更高位:改用内联样式(
style="color: red"),但破坏可维护性 - 升一位:把目标选择器本身带上 ID,比如从
#user-name改成#user-name.edit-mode((0,1,1,0)),再写规则时自然高于原 ID - 慎用
!important:它能破局,但会污染后续所有覆盖逻辑,且无法对抗用户样式表里的!important
最易被忽略的一点:权重和 DOM 结构深度、选择器“长度”、文件引入顺序都无关。只看你写了几个 ID、几个类、几个标签——盯住 (a,b,c,d),一位一位比,问题就清楚了。

