MDN 原文链接:CSS property value processing | MDN
CSS 属性值处理
CSS 属性值从开发者编写到最终呈现在屏幕上,会经历一系列的处理与渲染流程。大致可以分为两个阶段: 处理阶段 ( Processing stages )和 渲染阶段 ( Rendered values )。
主要的四个阶段如下:
-
确定 指定值 ( specified value ):这一步是 层叠 ( cascading )、继承 ( inheritance )或使用初始值 (initial value)的结果。
-
计算 计算值 ( computed value ):根据 CSS 规范来得到计算值。有些属性会因为上下文被"自动调整",比如带有
position: absolute
的span
标签,即使没有显式指定display
属性,依照 CSS 规范,position: absolute
会将display
的计算值调整为block
。 -
得到 应用值 ( used value ):由浏览器根据排版上下文进行布局得到。比如指定值
width: 50%
,它在计算布局时会根据父元素的实际宽度转成像素,比如400px
,这个400px
就是它的应用值。 -
得到 实际值 ( 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
属性最初分配的值,它由以下规则确定:
-
如果为属性显式指定了值,那么指定值就是这个。
-
如果没有显式指定,但这个属性是可继承的,那么继承父元素的。
-
如果没有显式指定,而且这个属性不可继承,那么使用初始值。
计算值(computed value)
计算值 是由指定值经过单位换算、自定义属性替换等计算后得到的值,是继承的基础值(子元素继承的是父元素的计算值),也是后续应用值生成的前置步骤。这是将相对单位和自定义属性等解析为绝对值之后、考虑布局特定信息之前得出的结果。
计算值由指定值计算而来,计算规则为:
-
处理特殊值:
inherit
,initial
,revert
,revert-layer
和unset
. -
参考该属性的规范说明表,根据其中的 "computed value"栏进行一系列计算。(在 CSS 的官方规范中,每一个 CSS 属性都有一个"定义表,其中就有"Computed value"一栏,它指出这个属性在计算阶段会变成什么样)
计算值涉及的计算通常包含把相对值转换为绝对值(比如 em
、var()
转换为 px
、设置的值)。
这个阶段 尚未涉及布局相关信息 ,所以对于一些依赖于父元素尺寸或上下文的属性(如 width
、margin-right
、top
、left
、height
等),如果指定为百分比,在计算值阶段并不会转换为绝对单位(如 px
),而是保留为百分比的计算值,直到布局阶段再进行解析。因此这类属性的 计算值 并不是最终用于渲染的值。
比如 line-height
属性,如果值是没有单位的数字,那这个值就是计算值。但这些计算值中的相对值会在应用值确定后,才转换成真正的绝对值。
应用值(used value)
应用值是在对计算值进行了所有计算,并根据布局的具体细节(例如,将百分比解析为实际像素值)对其进行细化后的属性值。
每一个CSS 属性都有一个应用值,也就是说,不论你写的值是相对的(em
, %
, auto
, 等等)还是模糊的(比如 inherit
, initial
),浏览器最终都会解析成一个明确、用于排版的值。
-
width
、height
、line-height
这种 和尺寸有关的属性 ,它们的 应用值 最终都是像素值(px)。 -
而简写属性(shorthand properties) 的应用值与 组成它的属性、
position
、float
等相关属性保持一致性。
简写属性这里有些拗口,举个栗子🌰:
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()
返回的是计算值,但也有少数(比如 width
、height
、padding
)返回应用值。
这是因为CSS 2.0 把 计算值(computed value) 定义为一个属性计算的最后一步,而CSS 2.1,它新增了一个新的术语:应用值(used value)。
CSS2.1 重新定义了 计算值 为布局前的值,应用值 布局后的值 。为了兼容以前的应用值,于是诞生了解析值。所以一些旧的属性(如width
、height
、padding
等),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 属性值从写下到真实渲染出来的四个流程,分别是 指定值 、计算值 、应用值 、实际值 。我们还从 处理阶段 和 渲染值 方面介绍了相关术语。此外还有一些注意点:初始值≠用户代理样式表的默认值 、不是所有的属性都在 计算值阶段 完全转换为具体值。
感谢观看!🌸
有误的地方恳请批评指正,笔者会在第一时间进行修改。