描述 CSS 属性值从声明值、层叠值、指定值、计算值、使用值到实际值的完整处理过程。
我们写在 CSS 里的值,浏览器不会直接拿去绘制页面。
浏览器会先判断哪个声明生效,再处理继承、初始值、相对单位、布局约束等问题,最后才得到真正用于显示的值。
这个过程大概可以分为:
声明值 -> 层叠值 -> 指定值 -> 计算值 -> 使用值 -> 实际值
简单来说就是: 浏览器先看写了什么,再决定谁生效;如果没有写,就看能不能继承;然后把一部分相对值换成更具体的值,最后用于布局和绘制。
1. 声明值
声明值就是我们在 CSS 规则中写出来的候选值。
.title {
color: red;
}
这里的 red 就是 color 的一个声明值。
但是一个元素可能被多个选择器选中,所以同一个属性可能会有多个声明值。
.title {
color: red;
}
.container .title {
color: yellow;
}
这时候,color 就有两个候选值:
red
yellow
之后的操作,就是从这些候选值中选出一个真正生效的值。
2. 层叠值
层叠值就是多个声明值中,通过层叠规则选出来的值。
常见判断维度包括:
- 来源和重要性:浏览器默认样式、用户样式、作者样式,以及是否有
!important - 选择器优先级:ID 选择器 > class 选择器 > 元素选择器
- 书写顺序:当前面规则都相同时,后写的规则会覆盖先写的规则
.title {
color: red;
}
.container .title {
color: yellow;
}
.container .title 的选择器优先级更高,所以 color: yellow 会胜出。
此时,yellow 就是 color 的层叠值。
3. 指定值
指定值是浏览器在层叠之后,为元素的每个 CSS 属性确定出来的值。
它可能来自三种情况:
- 如果有层叠值,就使用层叠值
- 如果没有层叠值,并且该属性可以继承,就继承父元素的计算值
- 如果没有层叠值,并且该属性不能继承,就使用该属性的初始值
比如 color、font-size 默认可以继承。
.parent {
color: red;
}
如果 .parent 里面的子元素没有单独设置 color,那么它会继承父元素的 color。
而 width、height、margin、padding 默认不会继承。如果没有声明值,浏览器会使用这些属性自己的初始值。
比如 width 的初始值是 auto,不是 0。
简单来说:
写了就用层叠后胜出的值;没写但能继承,就继承父元素;没写也不能继承,就使用属性的初始值。
但是: 指定值还不是最终用于绘制的值。它后面还会继续经过计算。
4. 计算值
计算值是指定值经过初步计算之后得到的值。
在这个阶段,一些相对单位会被转换成更具体的值。
html {
font-size: 16px;
}
.title {
font-size: 2rem;
}
对于 .title 来说:
指定值:2rem
计算值:32px
因为 1rem 等于根元素 html 的字体大小,所以 2rem 会被计算成 32px。
不过,并不是所有相对值都会在计算值阶段变成具体的像素值。
例如:
.container {
width: 50%;
}
width: 50% 的计算值通常仍然是 50%。因为浏览器需要等到布局阶段知道父元素的宽度之后,才能计算出具体的像素值。
所以:
font-size: 2rem -> 计算值通常可以得到 32px
width: 50% -> 计算值通常仍然是 50%
5. 使用值
使用值是布局阶段真正使用的值。
有些属性的计算值还不能直接用于布局,需要结合上下文继续计算。
例如:
.parent {
width: 800px;
}
.child {
width: 50%;
}
对于 .child 来说:
指定值:50%
计算值:50%
使用值:400px
因为浏览器在布局阶段知道了父元素宽度是 800px,所以子元素的 50% 最终会被计算成 400px。
类似 auto、百分比高度、布局相关的尺寸,也经常需要到使用值阶段才能确定。
也就是说:
计算值不一定是最终布局时使用的值。
6. 实际值
实际值是浏览器最终用于绘制的值。
它通常和使用值很接近,但浏览器在真正绘制时,可能还会受到设备像素、字体渲染、小数像素取整等因素影响。
.container {
width: 33.3333px;
}
浏览器最终显示时,可能会根据设备像素比和渲染策略进行取整或映射。
可以简单理解为:
使用值更偏向布局计算结果
实际值更偏向最终渲染结果
所以: 声明值解决“写了什么”,层叠值解决“谁赢了”,指定值解决“没写怎么办”,计算值和使用值解决“具体是多少”,实际值解决“最终怎么画出来”。