FumadocsZDecode
CSS

CSS 优先级

CSS 优先级(Specificity)决定当多条规则同时匹配同一元素时,哪条规则最终生效。浏览器用一套三列计数器 [A, B, C] 来比较选择器权重:A 对应 ID 选择器数量,B 对应类/属性/伪类选择器数量,C 对应标签/伪元素选择器数量。比较时从左到右逐列进行,左列相等才比较右列。

权重速查表

类型示例权重
!importantcolor: red !important覆盖一切
内联样式style="color: red"[1,0,0,0]
ID 选择器#header[0,1,0,0]
类 / 属性 / 伪类选择器.btn / [type] / :hover[0,0,1,0]
标签 / 伪元素选择器p / ::before[0,0,0,1]
通配符 / 组合符 / :not()* / > / + / ~[0,0,0,0]
继承样式父元素传递下来的值无权重

各层级说明与示例

内联样式

内联样式写在 HTML 元素的 style 属性中,权重高于所有外部或内嵌样式表中的规则。

<!-- color: red 生效,外部样式表中的 p { color: blue } 不会覆盖它 -->
<p style="color: red;">Hello</p>

ID 选择器

每个 ID 选择器贡献一个 A 列计数。多个 ID 叠加时权重累加。

#nav { color: blue; }          /* [0,1,0,0] */
#nav #logo { color: red; }     /* [0,2,0,0] — 权重更高 */

类、属性与伪类选择器

每个此类选择器贡献一个 B 列计数。

.btn { color: blue; }              /* [0,0,1,0] */
.btn.active { color: green; }      /* [0,0,2,0] — 叠加后权重更高 */
[type="submit"] { color: purple; } /* [0,0,1,0] */
a:hover { color: red; }            /* [0,0,1,1] — 伪类 + 标签 */

标签与伪元素选择器

每个标签选择器或伪元素贡献一个 C 列计数。

p { color: black; }             /* [0,0,0,1] */
div p { color: gray; }          /* [0,0,0,2] — 两个标签 */
p::first-line { color: red; }   /* [0,0,0,2] — 标签 + 伪元素 */

通配符与组合符

*>、空格、+~ 以及 :not() 本身不贡献任何权重,但 :not() 内部的参数会计入。

* { margin: 0; }               /* [0,0,0,0] */
div > p { color: red; }        /* [0,0,0,2] — 仅两个标签计数 */
:not(.active) { opacity: 0.5 } /* [0,0,1,0] — .active 的权重计入 */

继承样式

继承自父元素的样式没有权重,任何直接应用于元素的规则(哪怕权重为 0)都会覆盖它。

body { color: blue; }  /* 子元素继承 blue,但没有权重 */
* { color: red; }      /* [0,0,0,0],仍然覆盖继承的 blue */

!important

!important 声明跳出正常权重比较流程,覆盖所有其他声明,包括内联样式。当两条规则都带有 !important 时,权重更高的选择器胜出。

#app p { color: blue !important; }   /* 胜出 — !important 且权重更高 */
p { color: red !important; }         /* !important,但权重低于上一条 */
p { color: green; }                  /* 不生效 */

避免滥用 !important,它会让样式难以预测和调试。仅在必须覆盖无法修改的第三方库样式时使用。

冲突解决示例

以下示例展示多条规则同时命中同一元素时的权重比较过程。

<div id="app">
  <p class="note">Hello</p>
</div>
p { color: black; }         /* [0,0,0,1] = 1   */
.note { color: blue; }      /* [0,0,1,0] = 10  */
#app p { color: red; }      /* [0,1,0,1] = 101 */

/* 最终 color: red — #app p 权重最高 */

权重相同时,写在后面的规则胜出(源码顺序决定)。

On this page