首页 / CSS 入门教程 / CSS 优先级

CSS 入门教程

CSS 优先级

本教程共 44 篇 · 第 44 篇 · 更新于 2026-07-29 · 约 14 分钟阅读

CSS优先级特异性层叠!important级联层

44. CSS 优先级

本节目标:理解 CSS 层叠规则,掌握特异性计算方法,能够正确处理样式冲突,了解级联层的使用场景。

当多条 CSS 规则作用于同一个元素时,浏览器怎么决定用哪个?这就是优先级(也叫特异性、specificity)要解决的问题。

层叠算法

浏览器处理样式冲突有一套完整的流程:

  1. 相关性:筛选出匹配当前元素的规则
  2. 来源和重要性:按来源(浏览器、开发者、用户)和 !important 排序
  3. 特异性:来源相同时,比较选择器的特异性
  4. 作用域距离:特异性相同时,比较作用域距离
  5. 出现顺序:以上都相同时,后写的规则胜出

简单说就是:先看点有没有匹配,再看来源和重要性,然后算特异性,最后看谁后写。

来源优先级

CSS 有三大来源,优先级从低到高:

来源说明
浏览器样式(user-agent)浏览器默认样式,比如 <h1> 默认加粗
用户样式(user)用户自定义的样式(很少用)
作者样式(author)开发者写的样式

开发中写的样式都是”作者样式”,优先级高于浏览器默认样式。这就是为什么我们写的 CSS 能覆盖浏览器默认样式。

特异性计算

特异性是一个三元组:(ID数, 类数, 元素数)。比较时从左到右,ID 列权重最高。

选择器类型权重示例
行内样式最高style="color: red"
ID 选择器1-0-0#nav
类/属性/伪类0-1-0.btn[type]:hover
元素/伪元素0-0-1div::before
通配符0-0-0*

计算示例:

h1                          /* 0-0-1 → 1 */
.title                      /* 0-1-0 → 10 */
#nav                        /* 1-0-0 → 100 */
.content h1                 /* 0-1-1 → 11 */
#nav .title                 /* 1-1-0 → 110 */
#nav .title:hover           /* 1-2-0 → 120 */
div#main .title.active      /* 1-2-1 → 121 */
<!DOCTYPE html>
<html lang="zh">
<head>
  <style>
    /* 特异性:0-0-1 = 1 */
    p { color: blue; }

    /* 特异性:0-1-0 = 10 */
    .text { color: green; }

    /* 特异性:0-2-0 = 20 */
    .text.highlight { color: orange; }

    /* 特异性:1-0-0 = 100 */
    #special { color: red; }
  </style>
</head>
<body>
  <p>蓝色(元素选择器)</p>
  <p class="text">绿色(类选择器)</p>
  <p class="text highlight">橙色(两个类)</p>
  <p class="text highlight" id="special">红色(ID 选择器)</p>
</body>
</html>

记忆口诀:ID > 类 > 元素。同一列里数量多的赢。不同列之间,左边的列永远比右边的列重要。

特殊情况

组合器不影响特异性

>+~、空格这些组合器本身不计入特异性:

.container p    /* 0-1-1 → 11 */
.container > p  /* 0-1-1 → 11(一样) */
p + p           /* 0-0-2 → 2 */

:is() 和 :not() 的特异性

:is():not() 本身不计入特异性,但它们参数中特异性最高的那个选择器会计入:

/* 特异性来自 #nav,即 1-0-0 */
:is(#nav, .menu) a   /* 1-0-1 → 101 */

/* 特异性来自 .active,即 0-1-0 */
:not(.active)        /* 0-1-0 → 10 */

:where() 始终为 0

:where() 会把特异性清零:

/* 特异性为 0-0-0 */
:where(#nav) a { color: red; }

/* 可以用很简单的选择器覆盖它 */
a { color: blue; }

继承的特异性为 0

从父元素继承来的样式,特异性为 0:

/* div 的 color 是 red(直接设置) */
div { color: red; }

/* p 继承 div 的 color,特异性为 0 */
div p { color: blue; } /* 直接选 p,0-0-1 > 0,所以是蓝色 */

/* 但如果是 span 继承 div */
div { color: red; font-size: 20px; }
span { font-size: 16px; } /* span 直接设置 font-size,覆盖继承 */

!important

!important 是优先级中的”王牌”,能覆盖几乎所有规则:

/* 即使 ID 选择器特异性更高,也赢不过 !important */
#title { color: red; }
.title { color: blue !important; } /* 胜出 */

!important 也有被覆盖的时候:

/* 后写的 !important 覆盖先写的 !important */
.title { color: blue !important; }
.title { color: red !important; } /* 胜出 */
<!DOCTYPE html>
<html lang="zh">
<head>
  <style>
    p { color: red !important; }
    #special { color: blue; }
    .text { color: green; }
  </style>
</head>
<body>
  <!-- 行内样式 + !important 才能覆盖作者的 !important -->
  <p class="text" id="special" style="color: orange !important;">
    橙色(行内 !important)
  </p>
  <p class="text" id="special">
    红色(作者 !important 覆盖了 ID 选择器)
  </p>
</body>
</html>

不要滥用

。一旦用了,只能用另一个 !important 覆盖,形成恶性循环。优先用提高选择器特异性的方式来覆盖。

合理使用场景

  • 覆盖第三方库的样式(无法修改源码时)
  • 工具类(.hidden { display: none !important; }
  • 用户样式表(无障碍需求)

级联层(@layer)

级联层是 CSS 较新的特性,让你从更高层面控制优先级:

/* 声明层,后面的层优先级更高 */
@layer base, components, utilities;

@layer base {
  button {
    background: gray;
  }
}

@layer components {
  .btn-primary {
    background: blue;
  }
}

@layer utilities {
  .bg-red {
    background: red;
  }
}

层内优先级再高,也抵不过外层(后声明)的普通样式:

@layer base {
  /* 特异性 1-0-0,但在层内 */
  #title { color: red; }
}

/* 不在层内,优先级高于层内规则 */
.title { color: blue; } /* 胜出 */
<!DOCTYPE html>
<html lang="zh">
<head>
  <style>
    @layer base, override;

    @layer base {
      /* 特异性很高,但在 base 层 */
      #app .title { color: red; }
    }

    @layer override {
      /* 特异性较低,但在更高优先级的层 */
      .title { color: blue; } /* 胜出 */
    }
  </style>
</head>
<body>
  <div id="app">
    <h1 class="title">蓝色(来自 override 层)</h1>
  </div>
</body>
</html>

级联层特别适合管理大型项目的优先级。把第三方库放到低优先级层,自己写的样式放到高优先级层,从根本上避免冲突。

解决样式冲突的步骤

当发现样式没生效时,按以下步骤排查:

  1. 检查选择器是否匹配:DevTools 看元素匹配了哪些规则
  2. 看有没有被划掉:被划掉的样式被更高优先级的规则覆盖了
  3. 比较特异性:被覆盖的选择器特异性是否低于覆盖它的
  4. 检查来源:浏览器默认样式、用户样式、作者样式的优先级
  5. 检查层:是否在级联层中,层的优先级如何

DevTools 的 Styles 面板会清晰展示所有匹配的规则,被覆盖的会显示删除线。

优先级速查表

优先级因素影响
!important提升为最高优先级(作者来源)
行内样式作者来源中最高(除了 !important)
级联层后声明的层优先级更高
特异性ID > 类 > 元素
出现顺序特异性相同时,后写的胜出
直接设置 vs 继承直接设置的优先级高于继承

最佳实践

不要用 ID 选择器写样式

ID 特异性太高,很难覆盖。用类代替:

/* 不好:特异性 1-0-0,很难覆盖 */
#submit-btn { background: blue; }

/* 好:特异性 0-1-0,容易覆盖 */
.btn-primary { background: blue; }

保持低特异性

特异性越低,越容易被覆盖,组件的可复用性越好:

/* 特异性 0-1-0 */
.card { background: white; }

/* 特异性 0-2-0,用于覆盖 */
.card.highlighted { background: yellow; }

用变量管理主题色

:root {
  --primary: #3498DB;
}

.btn {
  background: var(--primary);
}

/* 覆盖时只需改变量 */
.btn-danger {
  --primary: #E74C3C;
}

调试 CSS 时,先别急着加

。检查选择器特异性、层叠顺序,往往能找到更优雅的解决方案。

上一篇
CSS 函数
下一篇
已经是最后一篇啦