当前位置: 首页 > 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.dtcms.com/a/315782.html

相关文章:

  • 《C++初阶之STL》【模板参数 + 模板特化 + 分离编译】
  • @【JCIDS】【需求论证】联合能力集成与开发系统知识图谱
  • 机器学习通关秘籍|Day 03:决策树、随机森林与线性回归
  • 【工程化】tree-shaking 的作用以及配置
  • Android Framework代码屏蔽未接来电振动及声音通知
  • DHTMLX重磅发布React Scheduler组件,赋能日程管理开发!
  • SELinux加固Linux安全
  • 将普通用户添加到 Docker 用户组
  • 第十七天:原码、反码、补码与位运算
  • RAFT:让语言模型更聪明地用文档答题
  • Java从入门到精通 - 集合框架(一)
  • 最长连续序列(每天刷力扣hot100系列)
  • FastDeploy2.0:报qwen2.embed_tokens.weight
  • 2.4 组件通信
  • 24. 前端-js框架-Vue
  • Occ3D: A Large-Scale 3D Occupancy Prediction Benchmark for Autonomous Driving
  • Python高级编程与实践:Python性能分析与优化
  • Java技术栈/面试题合集(3)-Java并发篇
  • 【功能测试】软件功能上线测试经验总结
  • 场外个股期权的额度为何受限?
  • java web 服务员点餐系统demo 比较完整的前端后端+mysql + 图片上传 练习
  • 从审批流到审计链:刻录系统的全周期管控技术解析
  • Spring MVC框架中DispatcherServlet详解
  • 【开源工具】基于Python的PDF清晰度增强工具全解析(附完整源码)
  • LeetCode算法日记 - Day 2: 快乐数、盛水最多容器
  • 力扣经典算法篇-43-全排列(经典回溯问题)
  • vite面试题及详细答案120题(01-30)
  • 普通树状数组
  • 《Node.js与 Elasticsearch的全文搜索架构解析》
  • Leetcode 13 java