CSS重点知识-样式计算

众所周知,CSS 模块中最核心的两个概念是 包含块(Containing Block)样式计算(Style Computation)

本文将重点介绍 样式计算 的相关知识,也算是自己的一份学习笔记。


前言

我们都知道,浏览器在渲染页面时,主要由 渲染进程(Renderer Process) 负责完成整个可视化过程。它大致可以分为以下几个阶段:

  1. 解析 HTML → 构建 DOM 树
  2. 解析 CSS → 构建 CSSOM 树
  3. 合并 DOM + CSSOM → 生成 渲染树(Render Tree)
  4. 布局(Layout / Reflow) → 计算每个节点的大小和位置
  5. 绘制(Painting) → 将像素绘制到屏幕上
  6. 合成(Compositing) → 将不同层的内容合成为最终画面

在这个流程中,有一个非常关键却常被忽视的步骤 ------ 样式计算(Style Computation)

当浏览器完成 DOM 和 CSSOM 的构建后,它并不能立刻生成渲染树。

因为浏览器还需要先确定每个元素 最终的样式 ,包括颜色、字体、宽高、边距、定位等。

这些属性值往往受到多种因素影响,比如样式继承、层叠优先级、默认样式、相对单位(如 em%)等。

而浏览器为了得到这些确定的、可用于绘制的具体样式值,就会执行 样式计算 这一过程。


什么是样式计算

当我们为一个元素编写样式后,浏览器会根据这些样式对页面进行渲染。

在这个过程中,浏览器并不是直接把你写的样式原封不动地应用到元素上,而是会对其进行一系列计算与处理

最终生成一份完整的样式表。这些经过计算后的样式,才是页面最终展示出来的效果。

如下图所示,当我们在浏览器开发者工具中选中一个元素时,可以在 "计算样式(Computed)" 面板中看到该元素最终的样式属性。

打开全部显示,你会发现,这里不仅包含了我们自己编写的样式,还包括了许多额外的属性值------这些都是浏览器在样式计算阶段自动生成的。

例如,下图中我只为元素设置了 overflowborder 两个样式属性,

但在计算样式 中却能看到大量属性,包括 background-size 等我们并未显式定义的值。

这就引出了一个问题:

为什么我们只写了少量样式,浏览器却为元素生成了这么多属性?

这些属性的值是从哪里来的?

接下来,我们就来深入了解浏览器是如何完成这一过程的------样式计算(Style Computation)


样式计算过程

CSS 的样式计算主要分为四个步骤:

  1. 确定声明值(Specified Value)
  2. 层叠(Cascade)
  3. 继承(Inheritance)
  4. 使用默认值(Default Value)

属性值的计算过程是要保证每一个CSS属性都要有值

下面我们逐步解析每个阶段的作用与原理。


确定声明值(Specified Value)

在计算声明值之前,我们需要先观察浏览器的 样式表来源,主要分为两类:

  1. 浏览器默认样式表(User Agent Stylesheet)
    浏览器内部为每个元素定义了一套默认样式,以保证页面在没有任何 CSS 的情况下也能正常显示。
    例如,对于 <div> 元素,浏览器通常会设置 display: block 所以<div>是个块盒。
  1. 作者样式表(Author Stylesheet)
    即我们自己编写的 CSS 样式。

在这一阶段,浏览器会先找到两类样式表中没有冲突的属性,直接作为元素的初步计算值。

如下图所示:

  • 我们给 <div> 添加了 border 属性,但浏览器默认样式表没有定义该属性,那么 border 就直接成为计算样式的一部分。
  • 对于 display 属性,默认样式表和作者样式表都存在值(冲突情况),这时暂时不处理,后续会在 层叠 阶段统一解决。

层叠(Cascade)

层叠是样式计算中非常关键的一步,它的主要作用是解决多个规则冲突的属性值,最终确定元素的计算样式。

层叠过程主要包括三个步骤:

  1. 比较重要性(Importance)
  2. 比较特殊性(Specificity / 权重)
  3. 比较源次序(Source Order)

1. 比较重要性(Importance)

浏览器会根据样式的重要性来确定优先级,重要性从高到低如下:

  1. 带有important的作者样式
  2. 带有important的默认样式
  3. 作者样式
  4. 默认样式

2. 比较特殊性(Specificity / 权重)

如果多个规则的重要性相同,浏览器会根据选择器的特殊性 来决定哪条规则生效。 通常表示为: (inline, ID, class/属性/伪类, 元素/伪元素)

权重计算规则如下:

类型 计数方式
内联样式(style) 如果元素有内联样式,计为 1;否则 0
ID 选择器 ID 的数量累加
类、属性、伪类 数量累加
元素、伪元素 数量累加

示例:

ini 复制代码
<div id="main" class="container">
  <p class="highlight" style="color: green;">Hello World</p>
</div>

对应的 CSS:

css 复制代码
/* 规则 1 */
p { color: black; }

/* 规则 2 */
.container p { color: blue; }

/* 规则 3 */
#main p.highlight { color: red; }

权重规则(四元组表示):

规则 选择器 权重 说明
规则 1 p (0,0,0,1) 元素选择器 1 个
规则 2 .container p (0,0,1,1) 类选择器 1 个 + 元素选择器 1 个
规则 3 #main p.highlight (0,1,1,1) ID 1 + 类选择器 1 + 元素选择器 1
内联样式 style="color: green;" (1,0,0,0) 内联样式权重最高

比较结果:

浏览器会选择权重最高的规则生效 (高位比较)

  • 内联样式 (1,0,0,0) > 规则 3 (0,1,1,1) > 规则 2 (0,0,1,1) > 规则 1 (0,0,0,1)
  • 所以最终 <p> 元素的 color 属性为 绿色(内联样式生效)

在平时开发的时候,编辑器其实自带了权重查看(这里没有内联样式,只展示后三位),如下所示:


3. 比较源次序(Source Order)

重要性和特殊性都相同 时,浏览器会选择后定义的规则生效,即 CSS 文件中后出现的规则覆盖前面的规则。


继承(Inheritance)

当一个属性未被显式指定 ,并且该属性是可继承的 (如 colorfont-sizeline-height 等),

浏览器会自动从父元素继承该属性的计算结果,用于当前元素。


使用默认值(Default Value)

对于那些既没有指定样式也不可继承 的属性,浏览器会使用该属性在规范中定义的默认值 (即 initial value)。


💡 核心总结

CSS 样式计算就是浏览器将所有样式规则整理成最终可渲染的样式的过程,核心流程是:

收集声明值 → 层叠解决冲突 → 继承父元素样式 → 补充默认值

相关推荐
yoyoma7 小时前
object 、 map 、weakmap区别
前端·javascript
shyshi7 小时前
vercel 部署 node 服务和解决 vercel 不可访问的问题
前端·javascript
.生产的驴7 小时前
React 模块化Axios封装请求 统一响应格式 请求统一处理
前端·javascript·react.js·前端框架·json·ecmascript·html5
前端大神之路7 小时前
vue2 响应式原理
前端
一个努力的小码农7 小时前
Rust中if let与while let语法糖的工程哲学
前端·rust
雾岛听风来7 小时前
Android开发中常用高效数据结构
前端·javascript·后端
IT_陈寒7 小时前
Vue 3性能优化实战:这5个Composition API技巧让你的应用快30%
前端·人工智能·后端
IT_陈寒7 小时前
Vue3性能翻倍的5个秘密:从Composition API到Tree Shaking实战指南
前端·人工智能·后端
IT_陈寒7 小时前
JavaScript 性能优化:3个V8引擎隐藏技巧让你的代码提速50%
前端·人工智能·后端