当前位置: 首页 > backend >正文

“Why“比“How“更重要:层叠样式表CSS

在开始之前,我们先抛出一些问题:

CSS是在什么背景下出现的?

你知道我们常说的CSS3标准是按模块推出的吗?

为什么入门要从盒模型开始?

CSS是如何参与浏览器中渲染部分的?


一、CSS的历史

CSS目前一共迭代了CSS1.0、2.0两个版本,目前正在全面迈向3.0。

CSS 1.0

1991年2月W3C发布一个有关样式的标准CSS1.0。这个版本包含了font(字体)的相关属性、颜色与背景的相关属性、文字的相关属性、box的相关属性。

CSS 2.0

1998年5月,CSS2.0推出。推荐内容和表现效果分离的方式,开始使用样式表结构。

(将HTML和CSS分离,通过导入CSS文件到HTML文件,使用外联样式表)

CSS 3.0

CSS3.0标准并没有被W3C官方统一并推出。

2001年,W3C着手开始准备开发CSS第三版规范。但我们很难谈论CSS3.0标准。

CSS3.0的新特性是被构建为一系列(理论上)相互独立的模块(百度百科指出共计32个独立模块),而不是整体的单一的规范。

“模块化 CSS3 的基本原理是,每个模块都可以按照自己的速度工作,而且特别重要的(或流行的)模块可以按照 W3C 的进度前进,而不会受到其他模块的阻碍。”


二、对HTML元素分类标准

CSS依赖于元素,但并不是所有元素都是平等的。

HTML元素名称更多是语义上的区别,不同元素之间设置属性进行转换达到相同的效果。

浏览器默认对HTML元素添加默认的属性导致语义不同元素有不同的CSS效果(User Agent Stylesheet)

维度一:替换元素和非替换元素

替换元素(Replaced Element)

  • 内容由外部资源定义
  • 尺寸受内在属性约束
  • 渲染时替换内容区域
<img src="image.jpg">       <!-- 图像资源 -->
<video controls></video>     <!-- 视频资源 -->
<iframe src="..."></iframe>  <!-- 嵌套文档 -->
<input type="image">        <!-- 图像按钮 -->
<embed type="...">          <!-- 插件内容 -->

非替换元素(Nonreplaced Element)

  • 内容直接包含在文档中
  • 完全由CSS控制表现
  • 支持伪元素修饰
<div>文本内容</div>       <!-- 块级容器 -->
<span>行内文本</span>     <!-- 行内文本 -->
<p>段落元素</p>          <!-- 文本段落 -->
<button>按钮</button>     <!-- 表单按钮 -->
<ul><li>列表项</li></ul> <!-- 列表结构 -->

维度二:块级元素和行内元素

块级元素:

  • 默认占满整行​
  • 可以设置宽高/边距
  • 强制前后换行
/* 标准块元素 */
div, p, h1-h6, section, main/* 列表相关 */
ul, ol, li, dl, dd/* 表格结构 */
table, tr /* (特例) */

行内元素:

  • 默认跟随文本流​
  • 不强制换行
  • 尺寸由内容决定
/* 文本级元素 */
span, strong, em, a, code/* 表单元素 */
input, textarea, label/* 替换元素 */
img, video /* (同时也是替换元素) */

三、CSS学习重点清单

  • 与模块相关:重点「外联样式」(了解行内样式、内部样式),参考文章:在HTML中CSS三种使用方式_html 内部css-CSDN博客
  • 盒子模型(所有内容都被渲染成一个矩形框,这个矩形框就是盒子模型),了解怪异盒模型
  • 选择器的优先级(属性的应用规则)
  • 字体font
  • 背景background
  • 等等等等

四、浏览器渲染主线程如何解析CSS的?

官方定义:在 CSS 中,视觉格式化模型(visual formatting model)描述了用户代理如何获取文档树,并将其处理后显示在视觉媒体上。

浏览器渲染主线程如何解析CSS的过程就是视觉格式化模型。

1. 解析HTML,生产DOM和CSSOM

在渲染主线程将HTML解析为DOM和CSSOM树。

面对CSS的多种样式,如行内、内部样式、外部样式以及浏览器默认的User Agent StyleSheet,共计四种类型。

每一个这类关键词,都会在CSSOM树根节点下添加一个孩子节点。

可以在浏览器控制台打印document.styleSheets查看这颗树的节点。

图片来源:渡一教育

2. 样式计算

 在浏览器解析HTML后生存DOM和CSSOM树之后下一个阶段是计算样式,生成Computed Style:

1. 样式规则匹配(Style Rule Matching)

浏览器会遍历DOM树中的每个节点,并为每个节点匹配所有适用的CSS规则(来自CSSOM)。这包括:

  • 内联样式(style属性)
  • 内部样式表(<style>标签)
  • 外部样式表(<link>引入的CSS文件)
  • 用户代理样式(浏览器默认样式)

匹配规则基于CSS选择器

(明白为什么选择器很重要了吧?)

  • 浏览器会从CSS规则中选择与当前DOM节点匹配的选择器。
  • 匹配过程通常是从右向左进行(例如,对于选择器.box p,先找到所有p元素,再检查其祖先是否有.box)。
2. 层叠(Cascading)

当多个规则匹配同一个元素时,浏览器需要解决冲突,确定哪个规则的样式属性应该生效。这遵循CSS层叠规则:

  • 来源重要性​:!important > 用户代理样式 < 用户样式 < 作者样式(开发者写的样式)< 作者!important < 用户!important
  • 特异性(Specificity)​​:计算选择器的权重,通常按以下顺序:
    • 内联样式(权重最高)
    • ID选择器
    • 类选择器、属性选择器、伪类
    • 元素选择器、伪元素(权重最低)
  • 书写顺序​:后出现的规则覆盖前面的规则(在相同来源和特异性的情况下)。
3. 继承(Inheritance)

某些CSS属性如果没有显式指定,会从父元素继承(如font-sizecolor等)。浏览器会检查父元素的Computed Style,并将可继承的属性传递给子元素。

4. 默认值(Default Values)

如果没有任何规则指定某个属性,则使用该属性的默认值(例如,width默认为autofont-size默认为medium)。

5. 计算值(Computed Values)

在计算过程中,浏览器会将所有相对单位转换为绝对单位:

  • em → px
  • rem → px
  • % → 根据父元素的对应属性计算
  • vw/vh → px(基于视口尺寸)
  • 颜色值(如rgb()hsl())转换为rgba()
  • 简化calc()表达式

注意:此时计算的是Computed Value,而不是最终用于渲染的Used Value(布局后确定的值)。例如:

  • width: 50% → 计算值仍然是50%(因为还不知道父元素宽度)
  • 在布局阶段之后,才会计算出实际的像素值(Used Value)。

3.盒模型生成

. 确定盒子类型(基于display属性)

浏览器根据元素的display属性确定盒子类型:

  • 块级盒子​:

    • 生成块级格式化上下文(BFC)
    • 垂直排列,占据整行宽度
    • 可设置宽高、内外边距
    • 示例元素:<div><p><h1>-<h6>
  • 行内盒子​:

    • 生成行内格式化上下文(IFC)
    • 水平排列,不换行
    • 尺寸由内容决定
    • 示例元素:<span><a><strong>
  • 行内块盒子​:

    • 混合特性:外部行内,内部块级
    • 可设置宽高,水平排列
    • 生成BFC
    • 示例元素:<img><button><input>
  • 特殊盒子​:

    • 弹性盒子​:生成弹性格式化上下文(FFC)
    • 网格盒子​:生成网格格式化上下文(GFC)
    • 表格盒子​:生成特殊表格布局
    • 匿名盒子​:包裹未包含在元素中的文本内容

4.计算盒模型->布局计算->渲染树生成->分层绘制->合成显示

计算盒模型生成盒子结构

每种盒子类型生成对应的矩形结构。浏览器根据计算样式计算盒模型的四个区域,context-padding-border-margin。

特殊处理​:替换元素、表格、弹性/网格布局

生成最终盒模型​:综合所有计算结果

http://www.xdnf.cn/news/17025.html

相关文章:

  • 计算机网络:详解路由器如何转发子网数据包
  • MySQL 查询性能优化与索引失效问题全解析
  • 需求测试用例设计
  • 落霞归雁:从自然之道到“存内计算”——用算法思维在芯片里开一条“数据高速航道”
  • Vue3核心语法进阶(Props)
  • 【C# Winform】 Action事件驱动的多层数据传递
  • 8.5PPT总结各种攻击
  • 37.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--增加Github Action
  • Linux NFS 服务部署、客户端配置及 autofs 自动挂载操作指南
  • 嵌入式硬件中运放内部底层分析
  • 区块链:重构信任的价值互联网革命​
  • CNN卷积神经网络之注意力机制CBAM(六)
  • 【android bluetooth 协议分析 01】【HCI 层介绍 30】【hci_event和le_meta_event如何上报到btu层】
  • uniapp Android App集成支付宝的扫码组件mPaaS
  • Linux 内存管理之 Rmap 反向映射(二)
  • Kafka-Eagle 安装
  • 江协科技STM32学习笔记1
  • AlexNet训练和测试FashionMNIST数据集
  • 什么是越权漏洞?如何验证。
  • c++介绍
  • cJSON库应用
  • Python高级编程与实践:Python装饰器深入解析与应用
  • 【数据结构初阶】--排序(三):冒泡排序,快速排序
  • BeeWorks私有化即时通讯,局域网办公安全可控
  • Python基础框架
  • 改进的BP神经网络算法用于预测温度值的变化
  • 剑指offer第2版:字符串
  • jenkins插件Active Choices的使用通过参数动态控制多选参数的选项
  • java web 未完成项目,本来想做个超市管理系统,前端技术还没学。前端是个简单的html。后端接口比较完善。
  • mq_timedsend系统调用及示例