Appearance
✨CSS 属性值的计算过程 👌
1. 计算过程概述
CSS 属性值的计算过程 是浏览器渲染引擎为每个元素确定最终样式值的核心机制。
1.1 什么是属性值计算过程
属性值计算过程是指一个元素从所有属性都没有值,到所有属性都有确定值的完整计算流程。这个过程确保了每个元素的每个 CSS 属性都有一个明确的值,为后续的布局和渲染提供基础。
1.2 计算过程的重要性
- 渲染前提:元素渲染的前提条件是所有 CSS 属性必须有值
- 样式确定性:确保每个属性都有明确的计算结果
- 层叠解决:解决多个样式规则之间的冲突
- 继承机制:处理父子元素之间的样式传递
1.3 计算过程的基本流程
开始渲染元素
↓
所有属性都没有值
↓
经过四个计算阶段
↓
所有属性都有确定值
↓
开始布局和绘制2. 渲染机制
2.1 渲染顺序
浏览器按照页面文档的树形目录结构进行渲染,采用深度优先遍历的方式:
html
<!DOCTYPE html>
<html>
<head>
<title>渲染顺序示例</title>
</head>
<body>
<div class="container">
<!-- 1. 首先渲染 container -->
<header>
<!-- 2. 然后渲染 header -->
<h1>标题</h1>
<!-- 3. 渲染 h1 -->
<nav>
<!-- 4. 渲染 nav -->
<ul>
<!-- 5. 渲染 ul -->
<li>菜单1</li>
<!-- 6. 渲染第一个 li -->
<li>菜单2</li>
<!-- 7. 渲染第二个 li -->
</ul>
</nav>
</header>
<main>
<!-- 8. 渲染 main -->
<p>内容</p>
<!-- 9. 渲染 p -->
</main>
</div>
</body>
</html>2.2 DOM 树遍历过程
html
├── head
│ └── title
└── body
└── div.container
├── header
│ ├── h1
│ └── nav
│ └── ul
│ ├── li (菜单1)
│ └── li (菜单2)
└── main
└── p渲染引擎会按照这个树形结构,从根节点开始,逐个处理每个元素的样式计算。
2.3 渲染前提条件
每个元素的所有 CSS 属性必须有值,这是渲染的绝对前提:
css
/* 示例:一个div元素需要确定的属性值 */
div {
/* 显示相关 */
display: block; /* 必须有值 */
visibility: visible; /* 必须有值 */
/* 盒模型相关 */
width: auto; /* 必须有值 */
height: auto; /* 必须有值 */
margin: 0; /* 必须有值 */
padding: 0; /* 必须有值 */
border: none; /* 必须有值 */
/* 定位相关 */
position: static; /* 必须有值 */
top: auto; /* 必须有值 */
left: auto; /* 必须有值 */
/* 文本相关 */
color: black; /* 必须有值 */
font-family: serif; /* 必须有值 */
font-size: 16px; /* 必须有值 */
/* 背景相关 */
background-color: transparent; /* 必须有值 */
/* ...还有数百个其他属性都必须有确定值 */
}3. 四个计算阶段
属性值计算过程包含四个依次执行的阶段,每个阶段都有特定的作用和规则。
3.1 计算阶段概览
| 阶段 | 名称 | 作用 | 结果 |
|---|---|---|---|
| 1 | 确定声明值 | 收集所有适用的 CSS 声明 | 获得候选样式规则列表 |
| 2 | 层叠 | 解决样式冲突,确定最终声明 | 每个属性最多有一个声明值 |
| 3 | 继承 | 处理没有声明值的可继承属性 | 从父元素获取继承值 |
| 4 | 使用默认值 | 为仍然没有值的属性设置默认值 | 所有属性都有确定值 |
3.2 阶段执行流程
开始计算某个元素的某个属性
↓
阶段1:确定声明值
├─ 有声明值 → 进入阶段2
└─ 无声明值 → 跳到阶段3
↓
阶段2:层叠
├─ 解决冲突 → 确定最终声明值
└─ 计算完成
↓
阶段3:继承
├─ 属性可继承 → 从父元素继承
├─ 属性不可继承 → 进入阶段4
└─ 父元素无值 → 进入阶段4
↓
阶段4:使用默认值
└─ 使用属性的初始值
↓
计算完成,属性有确定值4. 阶段一:确定声明值
4.1 声明值的定义
声明值(Declared Values) 是指所有适用于当前元素的 CSS 声明中,针对特定属性的值。
4.2 声明值的来源
声明值可能来自多个不同的来源:
html
<!DOCTYPE html>
<html>
<head>
<style>
/* 1. 作者样式表 */
.container {
color: blue;
font-size: 16px;
}
#main {
color: green;
}
div {
color: red;
}
</style>
</head>
<body>
<!-- 2. 内联样式 -->
<div class="container" id="main" style="color: purple; font-weight: bold;">
这个元素的 color 属性有多个声明值: - 内联样式:purple - ID选择器:green -
类选择器:blue - 标签选择器:red - 浏览器默认样式:black(通常)
</div>
</body>
</html>4.3 声明值收集规则
浏览器会收集所有匹配当前元素的 CSS 规则:
css
/* 声明值收集示例 */
/* 通用选择器 */
* {
margin: 0; /* 声明值1 */
}
/* 标签选择器 */
div {
margin: 10px; /* 声明值2 */
color: black;
}
/* 类选择器 */
.box {
margin: 15px; /* 声明值3 */
padding: 20px;
}
/* ID选择器 */
#container {
margin: 25px; /* 声明值4 */
background: white;
}
/* 对于 <div class="box" id="container"> 元素:
margin 属性收集到4个声明值:0, 10px, 15px, 25px
color 属性收集到1个声明值:black
padding 属性收集到1个声明值:20px
background 属性收集到1个声明值:white
*/4.4 选择器匹配过程
html
<!DOCTYPE html>
<html>
<head>
<style>
/* 这些规则都会被收集 */
body div.content p {
color: red;
}
.content p {
color: blue;
}
p {
color: green;
}
.highlight {
color: yellow;
}
</style>
</head>
<body>
<div class="content">
<p class="highlight">
这个段落的 color 属性会收集到4个声明值: - body div.content p: red -
.content p: blue - p: green - .highlight: yellow
</p>
</div>
</body>
</html>5. 阶段二:层叠
参考层叠笔记
6. 阶段三:继承
当某个属性在前两个阶段都没有获得值时,进入继承阶段,具体内容参考继承笔记
7. 阶段四:使用默认值
7.1 默认值的定义
当属性在前三个阶段都没有获得值时,使用该属性的初始值(Initial Value)。
7.2 常见属性的默认值
css
/* 常见属性的默认值 */
/* 显示相关 */
display: inline; /* 大多数元素的默认值 */
visibility: visible;
opacity: 1;
/* 盒模型相关 */
width: auto;
height: auto;
margin: 0;
padding: 0;
border: none; /* 等同于 border: 0 none transparent */
box-sizing: content-box;
/* 定位相关 */
position: static;
top: auto;
left: auto;
z-index: auto;
/* 文本相关 */
color: black; /* 实际值取决于浏览器 */
font-family: serif; /* 浏览器默认字体 */
font-size: medium; /* 通常是16px */
font-weight: normal;
font-style: normal;
line-height: normal;
text-align: left; /* 在LTR语言中 */
text-decoration: none;
/* 背景相关 */
background-color: transparent;
background-image: none;
background-repeat: repeat;
background-position: 0% 0%;
/* 浮动和清除 */
float: none;
clear: none;
/* 溢出处理 */
overflow: visible;