CSS 属性值的计算与过程

今天我们来讲一个非常非常重要的知识点------CSS 的属性值计算过程

我经常说,CSS 里有两个核心知识点:

  1. 属性值的计算过程
  2. 视觉格式化模型

如果这两个没掌握,CSS 就没算真正学会。其它那些早期的、零碎的属性只是加深理解的练习,但核心就在这两个。


一、什么是属性值的计算过程

我们平时写网页、调试样式的时候,会在浏览器的「开发者工具」里看到很多属性值,有些是我们写的,有些是默认就存在的。 这时候你可能会想:我明明没写这么多属性,为什么调试结果里都有值?

这就是属性值计算过程的核心所在。

每一个 CSS 元素,不管你写没写它的样式,最终都必须有每一个属性的值。 不可能有属性"缺失"。 如果你没写,浏览器会帮你"算"出来。 而「属性值的计算过程」就是在研究------它到底是怎么一步步算出这些最终结果的。

理解这个过程非常关键。调样式的时候,如果某个样式不生效,或者显示结果和预期不一样,你就可以根据这个过程去反推问题出在哪里。


二、计算结果(Computed Value)

我们在开发者工具里看到的最终结果,就是计算结果(Computed Value)。 真正决定页面上元素最终长什么样的,不是你写的样式,而是计算后的结果。

举个例子:

css 复制代码
div {
  display: inline;
  float: left;
}

你写的 displayinline,但最终计算结果里会变成 block。 为什么?因为 floatdisplay: inline 是冲突的,浏览器会根据规则自动转换。

所以记住:写出来的不一定是最终值,计算结果才是决定因素。


三、属性值的计算四个阶段

属性值的计算大致分为四个步骤:

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

下面我们逐步讲解。


1. 确定声明值

在这一步,浏览器会去查找所有和该元素相关的样式来源,包括:

  • 用户编写的样式表(作者样式)
  • 浏览器默认样式表(用户代理样式)
  • 甚至用户自定义样式(很少用)

如果没有冲突(即同一个属性没有被多次声明),那么浏览器直接采用这个值。

同时,在这个阶段还会进行一些值的转换

  • 比如颜色 red 会被转换成 rgb(255, 0, 0)
  • 相对单位会被换算成绝对值
  • 某些语义值会被规则修正,比如 float:left 会让 display 变成 block

2. 层叠(Cascade)

层叠阶段就是解决冲突。 如果同一个属性被多个地方声明了,就要判断谁"赢"。

这一步分为三个子步骤:

(1)比较重要性(Importance)

从高到低的优先级为:

  • 行内样式(内联样式)
  • 作者样式表(自己写的)
  • 用户代理样式表(浏览器默认)
  • !important 最高优先级(能打破以上规则)

比如:

css 复制代码
h1 {
  font-size: 32px;
}

默认样式中 h1 的字体大小是 32px, 但你在样式表中写了 font-size: 50px;,那最终就是 50px。 因为你的样式表比浏览器默认样式表更重要。

如果默认样式里带了 !important,那它就可能覆盖你的设置。


(2)比较特殊性(Specificity)

这就是我们常说的"优先级"、"权重"。

浏览器会为每一个选择器生成 4 个数字(通常写成 a,b,c,d):

  1. a:是否是内联样式(写在 style="" 里)
  2. b:ID 选择器的数量
  3. c:类、伪类、属性选择器的数量
  4. d:标签、伪元素选择器的数量

举例:

css 复制代码
#app .title span { color: red; }

计算权重:

类型 数量 对应数值
内联样式 0 a=0
ID 1 b=1
类、伪类、属性 1 c=1
标签、伪元素 1 d=1

最终权重:0,1,1,1

比较规则: 从左到右依次比较,高位相同才比较低位。 所以,0,1,0,00,0,99,99 更高。


(3)比较来源顺序(Source Order)

如果上面两步都一样,那就看谁写得更靠后,后面的会覆盖前面的。


3. 继承(Inheritance)

层叠之后,有的属性还是没值,比如 colorfont-size 等文字类属性。 这时候浏览器会看它的父元素有没有设置该属性。

如果父元素有且该属性是"可继承的",那就继承下来。

比如:

html 复制代码
<div style="color: red;">
  <p>文字</p>
</div>

虽然 p 标签没写 color,但它的文字也是红色,因为继承了父元素的 color

注意:并不是所有属性都能继承,比如 marginborder 就不行。


4. 使用默认值(Initial Value)

如果经过前面三步,属性仍然没有值,那浏览器就会使用它的默认值

每个属性都有默认值(可以查 MDN)。 这样一来,每个元素的每个属性都保证有一个确定的值。


四、总结:属性值的完整计算过程

一个元素的每个属性,从"没有值"到"有值",完整经历了以下步骤:

  1. 确定声明值:找出样式表中的初始声明并进行基础转换。
  2. 层叠(Cascade):解决冲突,选出最终保留的声明。
  3. 继承(Inheritance):没有值的属性尝试继承父元素。
  4. 默认值(Initial Value):仍没有值的属性使用默认值。

最终得到的,就是浏览器用于渲染的「计算结果(Computed Style)」。


五、应用:如何调试样式问题

当你的样式"没生效"时:

  1. 打开浏览器开发者工具;

  2. 查看元素的「Computed」面板;

  3. 对比结果和预期;

  4. 如果不符,就按计算流程去反推:

    • 有没有被覆盖?
    • 有无更高权重的选择器?
    • 是否可继承?
    • 默认值是什么?

理解了计算过程,CSS 调试就会非常清晰。


六、延伸:它在浏览器中的位置

整个浏览器的渲染流水线(Render Pipeline)大致分为 7 个阶段:

  1. 样式计算(Style Calculation)
  2. 布局(Layout)
  3. 绘制(Paint)
  4. 分层(Layering)
  5. 合成(Compositing)
  6. 光栅化(Rasterization)
  7. 显示(Display)

属性值的计算过程,属于第一个阶段的核心内容。


一句话总结:

CSS 的属性值计算过程,就是浏览器确定每个元素每个属性"最终值"的完整过程。 掌握它,你就能真正读懂浏览器是怎么渲染网页的,也能彻底搞清楚为什么某个样式"不生效"。

相关推荐
云鹤_2 小时前
【Amis源码阅读】组件注册方法远比预想的多!
前端·低代码
xinfei2 小时前
ES6 新特性 从 ECMAScript 2015(ES6)到 ECMAScript 2025
前端
GBVFtou3 小时前
vue响应式 track 和trigger 过程
前端
耀耀切克闹灬3 小时前
生成tag号的脚本
前端
搬运达人3 小时前
React v19.2.0更新
前端
电蚊拍3 小时前
ADB 实现手机访问电脑上运行的网站,真机调试H5网站
前端
浩男孩3 小时前
🍀上班摸鱼,手搓了个分页器组件
前端
朕的剑还未配妥3 小时前
vue2项目中使用markdown-it插件教程,同时解决代码块和较长单词不换行问题
前端
清羽_ls3 小时前
前端代码CR小知识点汇总
前端·cr