关于 CSS 属性值处理

MDN 原文链接:CSS property value processing | MDN

CSS 属性值处理

CSS 属性值从开发者编写到最终呈现在屏幕上,会经历一系列的处理与渲染流程。大致可以分为两个阶段: 处理阶段Processing stages )和 渲染阶段Rendered values )。

主要的四个阶段如下:

  1. 确定 指定值specified value ):这一步是 层叠cascading )、继承inheritance )或使用初始值initial value)的结果。

  2. 计算 计算值computed value ):根据 CSS 规范来得到计算值。有些属性会因为上下文被"自动调整",比如带有 position: absolutespan 标签,即使没有显式指定 display 属性,依照 CSS 规范,position: absolute 会将 display 的计算值调整为 block

  3. 得到 应用值used value ):由浏览器根据排版上下文进行布局得到。比如指定值 width: 50%,它在计算布局时会根据父元素的实际宽度转成像素,比如 400px,这个 400px 就是它的应用值。

  4. 得到 实际值 ( actual value ):浏览器根据设备或渲染限制,对 应用值 做转换,得到 实际值 。比如 border: 0.5px solid black,理论上应该绘制 0.5px 宽度的边框,如果些浏览器或设备不支持半像素边框,就会转成 1px,实际渲染出来就是 1px;如果是某些高精度屏幕,那么实际会渲染出 0.5px

相关术语

处理阶段(Processing stages)

初始值(initial value)

初始值是定义在规范里的默认值,是否启用取决于属性的继承行为:

对于可继承属性,如果没有显示指定值,那么 initial 只在根元素自动使用,其他元素则继承父元素的应用值。常见的可继承属性如 color

对于不可继承的属性,初始值会应用到每个没有显式指定值的部分。常见的不可继承属性如 border

当然也可以手动指定某属性使用 initial 值。

值得注意的是,初始值与用户代理样式表提供的默认值是不同的 ,CSS 的初始值在规范表中被定义,更倾向于"规定";而用户代理样式表是浏览器设置的默认值,其中的样式可能已经覆盖了初始值。

指定值(specified value)

指定值是 CSS 文件或 style 属性最初分配的值,它由以下规则确定:

  1. 如果为属性显式指定了值,那么指定值就是这个。

  2. 如果没有显式指定,但这个属性是可继承的,那么继承父元素的。

  3. 如果没有显式指定,而且这个属性不可继承,那么使用初始值。

计算值(computed value)

计算值 是由指定值经过单位换算、自定义属性替换等计算后得到的值,是继承的基础值(子元素继承的是父元素的计算值),也是后续应用值生成的前置步骤。这是将相对单位和自定义属性等解析为绝对值之后、考虑布局特定信息之前得出的结果。

计算值由指定值计算而来,计算规则为:

  1. 处理特殊值: inherit, initial, revert, revert-layerunset.

  2. 参考该属性的规范说明表,根据其中的 "computed value"栏进行一系列计算。(在 CSS 的官方规范中,每一个 CSS 属性都有一个"定义表,其中就有"Computed value"一栏,它指出这个属性在计算阶段会变成什么样)

计算值涉及的计算通常包含把相对值转换为绝对值(比如 emvar() 转换为 px 、设置的值)。

这个阶段 尚未涉及布局相关信息 ,所以对于一些依赖于父元素尺寸或上下文的属性(如 widthmargin-righttopleftheight 等),如果指定为百分比,在计算值阶段并不会转换为绝对单位(如 px),而是保留为百分比的计算值,直到布局阶段再进行解析。因此这类属性的 计算值 并不是最终用于渲染的值。

比如 line-height 属性,如果值是没有单位的数字,那这个值就是计算值。但这些计算值中的相对值会在应用值确定后,才转换成真正的绝对值。

应用值(used value)

应用值是在对计算值进行了所有计算,并根据布局的具体细节(例如,将百分比解析为实际像素值)对其进行细化后的属性值。

每一个CSS 属性都有一个应用值,也就是说,不论你写的值是相对的(em, %, auto, 等等)还是模糊的(比如 inherit, initial),浏览器最终都会解析成一个明确、用于排版的值

  1. widthheightline-height 这种 和尺寸有关的属性 ,它们的 应用值 最终都是像素值(px)

  2. 简写属性(shorthand properties) 的应用值与 组成它的属性、 positionfloat 等相关属性保持一致性。

简写属性这里有些拗口,举个栗子🌰:

css 复制代码
background: red url(bg.jpg) no-repeat center / cover;

等价于:

css 复制代码
background-color: red;
background-image: url(bg.jpg);
background-repeat: no-repeat;
background-position: center;
background-size: cover;

也就是 background 最终的 应用值 是这些子属性的 应用值"组合"出来的。

再比如background 中用了 position 相关的子属性(比如 background-position: 50%),那么浏览器在计算它的 应用值 时,必须结合当前的定位上下文(即 position)来解析百分比是相对于谁的。

渲染值(Rendered values)

渲染出来的值称为 实际值actual value ),而通过脚本获取的值称为 解析值resolved value )。

实际值(actual value)

实际值是真正渲染在屏幕上的结果,由于设备分辨率、抗锯齿等渲染机制,可能和解析值有出入(例如 sub-pixel 渲染),如前文提到的边框宽度示例。得到实际值的过程如开头所述。

解析值(resolved value)

解析值是在应用了所有活动样式表,并且对值中包含的基本计算进行解析之后,所得到的那个值。它可能是计算值,也可能是使用值。

getComputedStyle() 方法会返回一个实时的 CSSStyleDeclaration 对象,其中包含应用到指定元素的所有 CSS 属性的解析值。每个解析值都是计算值或使用值,具体取决于属性。

大部分属性的 getComputedStyle() 返回的是计算值,但也有少数(比如 widthheightpadding)返回应用值。

这是因为CSS 2.0 把 计算值(computed value) 定义为一个属性计算的最后一步,而CSS 2.1,它新增了一个新的术语:应用值(used value)

CSS2.1 重新定义了 计算值 为布局前的值,应用值 布局后的值 。为了兼容以前的应用值,于是诞生了解析值。所以一些旧的属性(如widthheightpadding等),getComputedStyle() 返回应用值。

详情可以参考这里:CSS 对象模型 (CSSOM)| resolved-values

对比

名称 英文名 特点 & 示例
指定值 specified value 来自 CSS、继承或初始值,如 width: 50%
计算值 computed value 部分解析后的值,如 font-size: 1.5em(父元素为16px) 变成 24px
应用值 used value 真正用于布局的值,如 width: 400px
实际值 actual value 渲染出来的值,可能因设备差异略有偏差

总结

本篇文章介绍了 CSS 属性值从写下到真实渲染出来的四个流程,分别是 指定值计算值应用值实际值 。我们还从 处理阶段渲染值 方面介绍了相关术语。此外还有一些注意点:初始值≠用户代理样式表的默认值不是所有的属性都在 计算值阶段 完全转换为具体值

感谢观看!🌸

有误的地方恳请批评指正,笔者会在第一时间进行修改。

相关推荐
onebyte8bits1 小时前
CSS Houdini 解锁前端动画的下一个时代!
前端·javascript·css·html·houdini
行云流水62613 小时前
js实现输入高亮@和#后面的内容
前端·javascript·css
Bigger14 小时前
🍸 Apple Liquid Glass 设计理念与前端实现解析
前端·css·apple
轻语呢喃17 小时前
大厂面试(四):Flex弹性布局从原理到计算
css·flexbox
快起来别睡了17 小时前
CSS定位的奥秘:从文档流到position,一文讲透前端布局核心!
前端·css·程序员
走,带你去玩1 天前
uniapp 时钟
javascript·css·uni-app
啃火龙果的兔子1 天前
安全有效的 C 盘清理方法
前端·css
小桥风满袖1 天前
Three.js-硬要自学系列32之专项学习箭头辅助器
前端·css·three.js
睡不着先生1 天前
CSS Houdini解锁前端动画的下一个时代!
javascript·css·html