描述 CSS 属性值从声明值、层叠值、指定值、计算值、使用值到实际值的完整处理过程。

2022-09-15 03:35:27

我们写在 CSS 里的值,浏览器不会直接拿去绘制页面。

浏览器会先判断哪个声明生效,再处理继承、初始值、相对单位、布局约束等问题,最后才得到真正用于显示的值。

这个过程大概可以分为:

声明值 -> 层叠值 -> 指定值 -> 计算值 -> 使用值 -> 实际值

简单来说就是: 浏览器先看写了什么,再决定谁生效;如果没有写,就看能不能继承;然后把一部分相对值换成更具体的值,最后用于布局和绘制。

1. 声明值

声明值就是我们在 CSS 规则中写出来的候选值。

.title {
    color: red;
}

这里的 red 就是 color 的一个声明值。

但是一个元素可能被多个选择器选中,所以同一个属性可能会有多个声明值。

.title {
    color: red;
}

.container .title {
    color: yellow;
}

这时候,color 就有两个候选值:

red
yellow

之后的操作,就是从这些候选值中选出一个真正生效的值。

2. 层叠值

层叠值就是多个声明值中,通过层叠规则选出来的值。

常见判断维度包括:

  1. 来源和重要性:浏览器默认样式、用户样式、作者样式,以及是否有 !important
  2. 选择器优先级:ID 选择器 > class 选择器 > 元素选择器
  3. 书写顺序:当前面规则都相同时,后写的规则会覆盖先写的规则
.title {
    color: red;
}

.container .title {
    color: yellow;
}

.container .title 的选择器优先级更高,所以 color: yellow 会胜出。

此时,yellow 就是 color 的层叠值。

3. 指定值

指定值是浏览器在层叠之后,为元素的每个 CSS 属性确定出来的值。

它可能来自三种情况:

  1. 如果有层叠值,就使用层叠值
  2. 如果没有层叠值,并且该属性可以继承,就继承父元素的计算值
  3. 如果没有层叠值,并且该属性不能继承,就使用该属性的初始值

比如 colorfont-size 默认可以继承。

.parent {
    color: red;
}

如果 .parent 里面的子元素没有单独设置 color,那么它会继承父元素的 color

widthheightmarginpadding 默认不会继承。如果没有声明值,浏览器会使用这些属性自己的初始值。

比如 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;
}

浏览器最终显示时,可能会根据设备像素比和渲染策略进行取整或映射。

可以简单理解为:

使用值更偏向布局计算结果
实际值更偏向最终渲染结果

所以: 声明值解决“写了什么”,层叠值解决“谁赢了”,指定值解决“没写怎么办”,计算值和使用值解决“具体是多少”,实际值解决“最终怎么画出来”。