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

“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.lryc.cn/news/611350.html

相关文章:

  • sql调优总结
  • 分布式选举算法:Bully、Raft、ZAB
  • 【深度学习新浪潮】TripoAI是一款什么样的产品?
  • ORACLE多表查询
  • GaussDB 常见问题-集中式
  • 【带root权限】中兴ZXV10 B863AV3.2-M_S905L3A处理器刷当贝纯净版固件教程_ROM包_刷机包_线刷包
  • Java set集合讲解
  • 最长连续序列(每天刷力扣hot100系列)
  • python学智能算法(三十三)|SVM-构建软边界拉格朗日方程
  • 利用 Radius Resource Types 扩展平台工程能力
  • avue---upload 图片上传
  • Vue3核心语法进阶(Props)
  • 从汇编角度揭秘C++构造函数(1)
  • 【Lua】题目小练8
  • 超越注意力机制
  • Augmodo AI:零售门店智能货架管理平台
  • 8月5号打卡
  • Java: jwt 入门介绍(Introduction to JSON Web Tokens)
  • ENS-317 Modbus TCP / 通用模式网关
  • Shader开发(七)创建第一个Shader项目
  • 完整设计 之2: 变形金刚机器人Transformer
  • 最优化中常见的优化理论
  • Guava 与 Caffeine 本地缓存系统详解
  • Windows 11 使用Windows Hello使用人脸识别登录失败,重新录入人脸识别输入PIN后报Windows Hello安装程序白屏无响应的问题解决
  • nodejs 编码初体验
  • 艺术性与真实感并存:FLUX.1 Krea [dev] 开源模型速览
  • muc中的电压调节和电源控制回路?
  • 网络相关(AI回答)
  • Linux的NFS与Autofs配置指南
  • linux定时器管理 timer_*系统调用及示例