一、CSS层叠(Cascade)

层叠是CSS最核心的特性之一,它决定了当多个CSS规则应用到同一个元素时,哪些规则最终会生效。CSS会按照以下三个关键因素来决定样式的优先级:

1.1 重要性(Importance)

CSS规则的重要性从高到低依次为:

  • !important 声明的规则。

  • 内联样式(HTML元素style属性)。

  • 媒体查询中的样式。

  • 普通样式。

1.2 来源(Origin)

样式的来源也会影响优先级,从高到低为:

  1. 浏览器默认样式(带有 !important)。

  2. 用户自定义样式(带有 !important)。

  3. 作者样式表(带有 !important)。

  4. 作者样式表(普通规则)。

  5. 用户样式表(普通规则)。

  6. 浏览器/用户代理默认样式(不带 !important)。

说明:

  • 用户代理一般是指浏览器,用户是网站访问者,作者是开发人员。

  • 作者样式表是网页开发者或设计师为特定网站或网页定义的样式。

  • 用户样式表是由用户定义的样式,通常用于定制他们浏览网页时的视觉体验。

了解更多,请点击 《CSS中的六个起源桶》。

1.3 特异性(Specificity)

特异性是一个用来衡量选择器精确度的数值,通常用四位数字表示(a, b, c, d),其计算规则如下:

1.3.1 特异性计算方法
  1. 内联样式:a = 1(最高优先级)。

  2. ID选择器:b += 1(每个ID选择器加1)。

  3. 类选择器、属性选择器、伪类选择器:c += 1(每个这样的选择器加1)。

  4. 元素选择器、伪元素选择器:d += 1(每个这样的选择器加1)。

1.3.2 特异性比较
  • 比较时从左到右,前面的数字大的优先级更高。

  • 只有当左边数字相等时,才比较右边的数字。

  • 通配符( * )和组合符( + ,  > ,  ~ ,  空格)不影响特异性。

1.3.3 特异性示例
  • h1 → (0, 0, 0, 1)

  • .class → (0, 0, 1, 0)

  • #id → (0, 1, 0, 0)

  • style="" → (1, 0, 0, 0)

  • #nav .list li a:hover → (0, 1, 2, 2)

  • .nav > ul > li > a → (0, 0, 1, 3)

 1.3.4 顺序(Order)

当两个规则具有相同的重要性、来源和特异性时,后定义的规则 会覆盖先定义的规则。

二、CSS特异性(Specificity)深度解析

 2.1 特异性优先级图解
2.2 特异性计算技巧
  • 内联样式(style属性)始终具有最高优先级(除了!important规则)。

  • ID选择器的权重高于类、属性和伪类选择器。

  • 类选择器的权重高于元素和伪元素选择器。

  • 多个低权重选择器无法超过单个高权重选择器。

  • 例如:10个类选择器(0,0,10,0)仍然小于1个ID选择器(0,1,0,0)。

2.3 避免特异性问题的最佳实践
  • 尽量使用低特异性选择器,提高可维护性。

  • 避免使用 !important ,除非绝对必要。

  • 避免过多使用ID选择器,优先使用类选择器。

  • 使用语义化的HTML结构,减少嵌套选择器。

  • 采用BEM等命名约定,创建更精确但可控的特异性。

BEM (Block, Element, Modifier)

BEM是目前最流行的CSS命名方法论之一,它将CSS类名分为三个部分:

 1. Block (块)

  • 独立的、可复用的组件

  • 命名方式:使用简洁的单词,如 .header, .button, .card

2. Element (元素)

  • 块的组成部分,依赖于块而存在

  • 命名方式:块名 + 双下划线 + 元素名,如 .header__logo, .button__text, .card__title

3. Modifier (修饰符)

  • 用于修改块或元素的外观、状态或行为

  • 命名方式:块名/元素名 + 双连字符 + 修饰符名,如 .button--primary, .card__title--large

BEM示例:

/* Block */
.header {
  display: flex;
  justify-content: space-between;
}

/* Element */
.header__logo {
  width: 100px;
  height: 50px;
}

/* Modifier */
.header--sticky {
  position: fixed;
  top: 0;
  left: 0;
}

三、CSS继承(Inheritance)

继承是指子元素自动继承父元素的某些CSS属性值。这一机制有助于减少代码重复,保持样式的一致性。

3.1 可继承的属性

CSS中有许多属性是默认可继承的,主要包括:

分类

属性

文本相关属性

font-family,font-size,font-style,font-weight,color,line-height,text-align,letter-spacing,word-spacin

列表相关属性

list-style-type,list-style-position

表格相关属性

border-collapse

其他

visibility,cursor

3.2 不可继承的属性

以下属性通常不可继承:

分类

属性

布局相关

width,height,margin,padding,border

定位相关

position,top,left,right,bottom,z-index

背景相关

background-color,background-image

盒模型相关

display,float,clear

3.3 控制继承的CSS属性值

CSS提供了四个特殊值来控制继承行为:

  • inherit:强制继承父元素的样式。

  • initial:将属性重置为浏览器默认值。

  • unset:如果属性可继承则继承,否则重置为默认值。

  • revert:回退到上一层级的样式(如浏览器默认样式)。

3.4 继承的应用场景
  • 设置全局字体和文本样式,让整个页面继承。

  • 创建一致的文本颜色和排版系统。

  • 简化组件样式的编写。

四、层叠、特异性和继承的综合应用

4.1 实际案例分析

假设我们有以下HTML和CSS:

<div id="container" class="wrapper">
  <p class="text">Hello World</p>
</div>

/* 全局样式 */
body {
  color: black;          /* 可继承 */
  background-color: white; /* 不可继承 */
}

/* 类选择器 */
.wrapper p {
  color: blue;          /* 特异性: (0, 0, 1, 1) */
}

/* ID选择器 */
#container .text {
  color: red;           /* 特异性: (0, 1, 1, 0) */
}

/* 内联样式 */
<p class="text" style="color: green;">  /* 特异性: (1, 0, 0, 0) */

在这个例子中:

  • p元素会继承body的color: black,但会被 .wrapper p 覆盖为蓝色。

  • #container .text的特异性更高,会覆盖 .wrapper p,使文字变为红色。

  • 如果添加内联样式 style="color: green;" ,文字会变为绿色。

  • 要覆盖内联样式,需要使用 !important。

4.2 最佳实践总结
  • 规划选择器策略:在项目开始前确定选择器使用规范。

  • 保持特异性低:使用类选择器而非ID,避免深层嵌套。

  • 合理使用继承:利用可继承属性减少重复代码。

  • 避免使!important:一旦使用,会导致后续样式管理困难。

  • 文档化特殊情况:记录必要的高特异性规则,便于维护。

通过理解CSS的这三个核心特性,你就能更好地控制页面样式,避免样式冲突,编写更加可维护的CSS代码。