CSS基础学习:CSS选择器与优先级规则

CSS 基础学习系列:CSS 选择器与优先级规则(从入门到能 debug 常见坑)

CSS 选择器是 CSS 的“定位器”,优先级(Specificity)则是决定“谁的样式最终生效”的裁判。本文从最基础讲起,一步步到实际开发中最容易踩的坑。

一、CSS 选择器分类(常用到冷门)

分类语法示例权重(Specificity)说明与使用场景
通配选择器*0,0,0,0全局重置样式(慎用,性能差)
元素(类型)选择器div, p, a0,0,0,1基础标签样式
类选择器.btn, .card0,0,1,0最常用,复用性强
属性选择器[type="text"], [data-status="error"]0,0,1,0表单、自定义属性
伪类:hover, :first-child, :nth-child(2)0,0,1,0交互状态、结构位置
ID 选择器#header, #main0,1,0,0唯一元素(现代开发尽量少用)
内联样式<div style="color:red">1,0,0,0最高优先级(除 !important 外)
!importantcolor: red !important;超越一切(同属性)最高,但尽量避免使用
伪元素::before, ::after, ::first-letter0,0,0,1装饰性元素
组合/关系选择器div > p, .parent .child, li + li累加上下文关系
现代选择器:is(), :where(), :has()特殊(后面讲)降低/控制权重利器

二、优先级(Specificity)计算规则 —— 核心重点

现代浏览器使用 四位权重 来计算(从高到低):

a, b, c, d
↑   ↑   ↑   ↑
内联 ID 类/属性/伪类  元素/伪元素

计算规则(最权威的 MDN 标准):

  • d(千位):内联样式(style 属性) → 1
  • a(百位):ID 选择器个数 → 每个 #id +1
  • b(十位):类、属性、伪类个数 → 每个 .class / [attr] / :hover +1
  • c(个位):元素、伪元素个数 → 每个 div / p / ::before +1

比较规则从左到右逐位比较第一位不同就分胜负绝不进位

常见例子计算

选择器a (ID)b (类/属性/伪类)c (元素)权重写法解释
*0000,0,0,0通配
p0010,0,0,1元素
.btn0100,0,1,0
div.btn0110,0,1,1类 + 元素
#header .logo1100,1,1,0ID + 类
#header #logo2000,2,0,0两个 ID(不推荐)
ul > li.active:hover0220,0,2,2伪类 + 类 + 两个元素
<div style="color:red">1,0,0,0内联(最高,除 !important)
color: blue !important超越一切仅同属性内最高

经典面试/实战对比题

/* 权重:0,0,0,1 */
p { color: red; }

/* 权重:0,0,1,0 */
.intro { color: blue; }

/* 权重:0,0,1,1 */
p.intro { color: green; }

/* 权重:0,1,0,0 */
#special { color: orange; }
<p class="intro" id="special">文字颜色是?</p>

答案顺序(从高到低):

  1. #special → orange(ID 最高)
  2. p.intro → green(类+元素)
  3. .intro → blue(类)
  4. p → red(元素)

三、!important 的真相

  • !important 只在同属性上比较,且优先级高于一切(包括内联样式)
  • 同 !important 情况下,再看普通 specificity
  • 不带 !important 的规则永远输给带 !important 的规则(同属性)

建议能不用就不用,用了之后后期维护会非常痛苦。

四、现代 CSS 控制权重的神器(推荐学习)

  • :is()内部最高权重决定整个 :is() 的权重
  :is(#header, .main) .title { ... }  /* 权重取决于 #header 或 .main 哪个被匹配 */
  • :where()永远 0,0,0,0 权重(非常适合组件库/基础样式)
  :where(.card) .title { color: #333; }  /* 权重 0,0,0,0,可被 .title 轻松覆盖 */
  • :has() → 父选择器(权重 = 内部选择器权重)

五、优先级之外的层叠规则(Cascade)

当 specificity 相同时,遵循以下顺序(从高到低):

  1. Transition 中的声明(动画中)
  2. !important 用户代理(浏览器默认)
  3. !important 用户样式表
  4. !important 作者样式表
  5. 动画(animation)
  6. 作者样式表(我们写的)
  7. 用户样式表
  8. 浏览器默认

最常见规则源码中后出现的相同权重规则覆盖前面的

六、实用建议(防坑指南)

  1. 尽量使用类选择器,少用 ID(ID 权重太高,难覆盖)
  2. 避免 !important(除非 reset 或第三方库覆盖)
  3. 不要过度嵌套(增加无谓权重)
  4. 组件化开发 → 推荐 BEM / CSS Modules / Scoped(基本解决权重冲突)
  5. 调试技巧:浏览器开发者工具 → Computed → 看到所有规则 + 划掉的规则,能直观看到谁赢了
  6. 现代项目 → 多用 :where():is() 降低基础样式权重

小练习(自己算一算)

A: #sidebar .widget-title { color: navy; }
B: .sidebar-title { color: purple; }
C: div #sidebar h3.title { color: maroon; }
D: h3 { color: teal !important; }
<div id="sidebar">
  <h3 class="widget-title sidebar-title title">标题颜色是?</h3>
</div>

答案:D → teal(因为 !important 最高)

有任何选择器或优先级冲突的实际代码想分析,欢迎贴出来,我帮你算权重和解释为什么!

文章已创建 4426

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部