Skip to content

✨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;