CSS 类型与工作方式
在前面的章节中,你已经学习了 CSS 的基本语法、引入方式和测量单位。现在,让我们深入理解 CSS 是如何"生效"的——浏览器是如何处理多个样式来源,并最终决定元素应该显示成什么样子的。
样式的三种来源
CSS 样式可以来自三个不同的来源,它们按照优先级依次应用:
1. User Agent 样式(用户代理样式)
User Agent 样式是浏览器提供的默认样式,也被称为"浏览器默认样式"。每个浏览器都会为 HTML 元素提供一套默认的样式规则。
/* 浏览器默认样式示例(简化版) */
body {
margin: 8px; /* Chrome 的默认值 */
}
h1 {
font-size: 2em;
font-weight: bold;
margin: 0.67em 0;
}
p {
margin: 1em 0;
}
a {
color: blue;
text-decoration: underline;
}
特点:
- 每个浏览器都有自己的默认样式表
- 不同浏览器的默认样式可能略有不同
- 这是所有样式的"起点",优先级最低
查看默认样式: 你可以在浏览器的开发者工具中查看元素的默认样式。在 Chrome 中,打开开发者工具,选择元素,在"计算样式"面板中可以看到所有应用的样式,包括默认样式。
2. 作者样式(Author Styles)
作者样式是网页开发者编写的样式,包括:
- 内联样式:直接在 HTML 标签中使用
style属性 - 内部样式表:在 HTML 文档的
<head>中使用<style>标签 - 外部样式表:通过
<link>标签引入的独立 CSS 文件
<!-- 内联样式 -->
<p style="color: red;">这是内联样式</p>
<!-- 内部样式表 -->
<head>
<style>
p {
color: blue;
}
</style>
</head>
<!-- 外部样式表 -->
<head>
<link rel="stylesheet" href="styles.css">
</head>
特点:
- 这是你作为开发者主要编写的样式
- 优先级高于 User Agent 样式
- 内联样式优先级高于内部和外部样式表
3. 用户样式(User Styles)
用户样式是用户通过浏览器设置或扩展定义的样式。用户可能因为以下原因设置自定义样式:
- 可访问性需求:需要更大的字体、更高的对比度
- 个人偏好:喜欢特定的颜色方案或字体
- 浏览器扩展:某些扩展可能会注入样式
/* 用户可能通过浏览器扩展设置的样式 */
* {
font-size: 18px !important; /* 用户设置更大的字体 */
}
body {
background-color: #f0f0f0 !important; /* 用户设置背景色 */
}
特点:
- 优先级通常最高(特别是使用
!important时) - 用户可以通过浏览器设置或扩展来应用
- 大多数用户不会设置自定义样式
样式的优先级顺序
当多个样式来源同时存在时,浏览器按照以下优先级顺序应用样式(从低到高):
- User Agent 样式(最低优先级)
- 外部样式表(作者样式)
- 内部样式表(作者样式)
- 内联样式(作者样式)
- 用户样式(如果使用
!important) - 作者样式(如果使用
!important)(最高优先级)
示例
让我们看一个例子,理解样式是如何被应用的:
<!DOCTYPE html>
<html>
<head>
<!-- 外部样式表 -->
<link rel="stylesheet" href="styles.css">
<!-- styles.css 中:p { color: green; } -->
<!-- 内部样式表 -->
<style>
p {
color: blue; /* 这会覆盖外部样式表的绿色 */
}
</style>
</head>
<body>
<!-- 内联样式 -->
<p style="color: red;">这段文字是红色的</p>
<!-- 内联样式优先级最高,所以显示红色 -->
</body>
</html>
在这个例子中:
- 浏览器默认样式:可能设置
p为黑色 - 外部样式表:设置
p为绿色 - 内部样式表:设置
p为蓝色(覆盖绿色) - 内联样式:设置
p为红色(覆盖蓝色)
最终,这段文字会显示为红色,因为内联样式的优先级最高。
样式计算的工作流程
浏览器在渲染页面时,会按照以下步骤计算每个元素的最终样式:
步骤 1:收集所有样式规则
浏览器首先收集所有可能应用到元素的样式规则,包括:
- User Agent 样式表中的规则
- 外部样式表中的规则
- 内部样式表中的规则
- 内联样式中的规则
- 用户样式中的 规则
步骤 2:匹配选择器
对于每个元素,浏览器会检查哪些选择器能够匹配到这个元素:
<div class="container">
<p class="highlight">这是一段文字</p>
</div>
/* 规则 1:匹配 */
p {
color: black;
}
/* 规则 2:匹配 */
.highlight {
color: blue;
}
/* 规则 3:不匹配 */
.button {
color: red;
}
对于 <p class="highlight"> 元素,规则 1 和规则 2 都会 匹配。
步骤 3:计算特异性(Specificity)
当多个规则匹配同一个元素时,浏览器会计算每个规则的特异性,特异性高的规则会覆盖特异性低的规则。
特异性计算规则(简化版):
- 内联样式:特异性最高
- ID 选择器:每个 ID 加 100
- 类选择器、属性选择器、伪类:每个加 10
- 元素选择器、伪元素:每个加 1
/* 特异性:1(1 个元素选择器) */
p {
color: black;
}
/* 特异性:10(1 个类选择器) */
.highlight {
color: blue; /* 这个会覆盖上面的黑色 */
}
/* 特异性:100(1 个 ID 选择器) */
#special {
color: red; /* 这个会覆盖上面的蓝色 */
}
步骤 4:应用层叠规则
如果两个规则的特异性相同,浏览器会按照以下规则决定:
- 来源优先级:作者样式 > User Agent 样式
- 出现顺序:后出现的规则覆盖先出现的规则
- !important:使用
!important的规则优先级最高
/* 规则 1 */
p {
color: blue;
}
/* 规则 2:后出现,特异性相同,所以会覆盖规则 1 */
p {
color: red; /* 最终显示红色 */
}
/* 规则 3:使用 !important,优先级最高 */
p {
color: green !important; /* 最终显示绿色 */
}
步骤 5:处理继承
某些 CSS 属性会被子元素继承,某些则不会:
body {
color: blue; /* 会被继承 */
font-size: 16px; /* 会被继承 */
margin: 0; /* 不会被继承 */
border: 1px solid; /* 不会被继承 */
}
<body>
<p>这段文字会继承 body 的 color 和 font-size</p>
<!-- 但不会继承 margin 和 border -->
</body>
步骤 6:计算最终值
浏览器会计算每个属性的最终值,包括:
- 相对单位转换为绝对单位(如
em→px) - 百分比值根据上下文计算
- 简写属性展开为具体属性
.container {
font-size: 16px;
padding: 1em; /* 计算为 16px */
width: 50%; /* 根据父元素宽度计算 */
margin: 10px 20px; /* 展开为 margin-top/bottom/left/right */
}
工作流程示意图
让我们用一个简单的流程图来理解整个过程:
┌─────────────────────────────────────────┐
│ 1. 收集所有样式来源 │
│ - User Agent 样式 │
│ - 外部样式表 │
│ - 内部样式表 │
│ - 内联样式 │
│ - 用户样式 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 2. 匹配选择器 │
│ 找出所有能匹配到元素的规则 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 3. 计算特异性 │
│ 比较每个规则的特异性值 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 4. 应用层叠规则 │
│ - 来源优先级 │
│ - 出现顺序 │
│ - !important │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 5. 处理继承 │
│ 将可继承的属性传递给子元素 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 6. 计算最终值 │
│ - 单位转换 │
│ - 百分比计算 │
│ - 属性展开 │
└─────────────────────────────── ──────────┘
↓
┌─────────────────────────────────────────┐
│ 最终样式应用到元素 │
└─────────────────────────────────────────┘
实际示例
让我们通过一个完整的例子来理解整个过程:
<!DOCTYPE html>
<html>
<head>
<style>
/* 规则 1:特异性 = 1 */
p {
color: black;
font-size: 14px;
}
/* 规则 2:特异性 = 10 */
.highlight {
color: blue;
}
/* 规则 3:特异性 = 11 (10 + 1) */
p.highlight {
font-size: 18px;
}
</style>
</head>
<body>
<p class="highlight">这是一段高亮文字</p>
</body>
</html>
样式计算过程:
- 收集规则:找到规则 1、2、3
- 匹配选择器:三个规则都匹配
<p class="highlight"> - 计算特异性:
- 规则 1:特异性 = 1
- 规则 2:特异性 = 10
- 规则 3:特异性 = 11
- 应用层叠规则:
color: blue(规则 2,特异性 10 > 规则 1 的 1)font-size: 18px(规则 3,特异性 11 > 规则 1 的 1)
- 最终结果:
- 文字颜色:蓝色
- 字体大小:18px
为层叠规则做铺垫
理解 CSS 的工作方式,特别是样式的来源和优先级,是学习"层叠规则"的基础。在下一部分《选择器与层叠规则》中,你将深入学习:
- 层叠(Cascade):多个样式规则如何合并
- 继承(Inheritance):样式如何从父元素传递到子元素
- 特异性(Specificity):如何精确计算选择器的优先级
- !important:如何使用和避免这个"最后的手段"
这些概念都建立在你对 CSS 工作方式的理解之上。现在,你已经知道了样式来自哪里,以及它们是如何被应用的。接下来,我们将深入学习如何精确控制样式的优先级和继承。
小结
CSS 样式来自三个主要来源:
- User Agent 样式:浏览器默认样式,优先级最低
- 作者样式:开发者编写的样式(内联、内部、外部),优先级中等
- 用户样式:用户自定义样式,优先级最高(特别是使用
!important时)
浏览器计算样式的流程包括:
- 收集所有样式规则
- 匹配选择器
- 计算特异性
- 应用层叠规则
- 处理继承
- 计算最终值
理解这个过程有助于你:
- 预测样式如何被应用
- 调试样式冲突问题
- 编写更可维护的 CSS 代码
- 为学习层叠规则打下基础
在下一部分,我们将深入学习选择器和层叠规则,让你能够精确控制样式的应用。