跳到主要内容

选择器权重计算方式(Specificity):怎么“算分”、怎么“比大小”?

面试速答(30 秒版 TL;DR)

  • 选择器权重(Specificity)常用四段记法:A-B-C-D(逐列比较,不做加法)。
  • 计算规则(面试够用版):
    • A:内联样式(style="")算 1(注意:这是“内联声明”的权重,不是选择器片段)。
    • B#id 每个 +1。
    • C.class[attr]:hover/:focus/:nth-child(...) 等伪类每个 +1。
    • Ddiv 等标签、::before/::after 等伪元素每个 +1。
  • *、组合符(空格、>+~)都不加分。
  • :where(...) 特例:它本身和参数都计为 0!important 不属于权重计算(它属于层叠的“重要性赛道”)。

这篇只讲“权重怎么算”。更完整的层叠比较顺序建议看:CSS 不同选择器的权重与层叠规则


一、权重到底在解决什么问题

当同一元素的同一属性被多条 CSS 声明同时命中时,浏览器需要决定“听谁的”。在层叠(Cascade)流程里,权重是其中一关,用来比较“选择器谁更具体”。

关键提醒:很多“我算出来权重更大却没生效”的问题,其实是输在:

  • !important
  • @layer
  • 书写顺序(权重打平时后写覆盖先写)

二、A-B-C-D 四段法(可直接背)

选择器/声明片段计入段例子
内联样式(声明)A + 1<div style="color:red">
ID 选择器B + 1#app
类选择器C + 1.card
属性选择器C + 1[disabled][type="text"]
伪类C + 1:hover:focus:not(...):is(...)
标签选择器D + 1diva
伪元素D + 1::before::marker

不加分(高频坑):

  • * 通配符:0
  • 组合符:0(空格、>+~
  • :where(...):0(包括参数)

三、比较规则:逐列比较,不做加法

权重比较是“字典序”:

  1. 先比 A
  2. A 相同再比 B
  3. B 相同再比 C
  4. C 相同再比 D

例子(面试常用):

  • 0-1-0-0(一个 ID)永远大于 0-0-999-999(再多 class/tag 也赢不了 ID)
  • .a .b.a > .b 权重相同:都是 0-0-2-0(组合符不计分)

四、现代伪类的“特殊计分规则”(建议背 3 个)

1):is(...) / :not(...) / :has(...)

它们本身当作伪类,但权重按参数选择器来算(面试表达法:取参数里“最强的那一个”的权重)。

/* :is(.a, #b) 的权重相当于 #b(因为 #b 更“强”) */
.x :is(.a, #b) {
color: red;
}

常见误区:有人以为逗号里的每个都“累计加分”,这是错的。

2):where(...)

:where(...) 的权重恒为 0:参数再具体也不加权重

/* 权重 = 0:它通常用于“写默认样式但不抢权重” */
:where(.btn.primary #danger) {
color: #c00;
}

3):nth-child(...) / :nth-of-type(...)

它们属于伪类,计入 C + 1。括号里的 2n+1 不影响权重;但如果写了 of <selectorList>(较新语法),会按其中选择器带来的规则计算(面试可简单说“它也是按参数选择器算”)。


五、典型题与标准答法(可直接照读)

Q1:.a#b#b 谁更大?

.a#b 更大。#b0-1-0-0.a#b0-1-1-0

Q2:为什么我把 HTML 里 class 顺序换了,样式没变?

:class 在 HTML 里的先后顺序不参与权重比较。权重打平时通常比的是“CSS 书写顺序(后写赢)”。

Q3:!important 算不算权重?

:不算。!important 是层叠里更靠前的一关,属于“重要性赛道”,不是 Specificity 的计分项。


易错点/坑

  • 把权重当成“加法总分”去比较(错,逐列比)。
  • 认为组合符会加分(错)。
  • :where() 还在按参数算分(错,恒 0)。
  • 只会算权重,不会排层叠的前置关卡:!important@layer、书写顺序。

速记要点(可背诵)

  • 权重 A-B-C-D:内联 / ID / class-attr-伪类 / tag-伪元素。
  • 逐列比,不做加法;组合符和 * 不加分。
  • :where() 恒 0;:is/:not/:has 按参数里最强的算。