在我看了超多篇资料,以及手动实践以后,总算总算,搞清了 web 图片的加载和渲染时机。啊,我需要掌声 👏👏👏~
开始步入主题了啊!准备!冲!
1. 浏览器工作流程
图片版:
webkit 引擎
文字版:
- 解析 HTML —> 构建 DOM 树
- 加载样式 —> 解析样式 —> 构建样式规则树
- 加载 JavaScript —> 执行 JavaScript 代码
- 结合 DOM 树和样式规则树来构建渲染树
- 计算元素位置进行布局
- 绘制
2. 图片的加载和渲染时机
- 解析 HTML
【遇到<img>标签加载图片】
—> 构建DOM树 - 加载样式 —> 解析样式
【遇到背景图片链接不加载】
—> 构建样式规则树 - 加载 JavaScript —> 执行 JavaScript 代码
- 结合 DOM 树和样式规则树来构建渲染树
【遍历DOM树,加载对应样式规则上的背景图片】
- 计算元素位置进行布局
- 绘制
【开始渲染图片】
总结:
1. 加载图片时机:
解析 HTML 时候
构建渲染树的时候
2. 渲染图片时机:
最后绘制页面时
只要掌握这个总结,再去对应相应规则,很快就能理解图片到底加载与否啦~
3. 上例子
3.1 元素 display: none
-
页面说明:页面上有个
img
和 含有背景图的div
,两者都设置了display: none
;<style> img { display: none; } .bg-wrapper { display: none; background-image: url("./blue.png"); } </style> <img src="./green.png" /> <div class="bg-wrapper"></div>
-
图片资源加载情况:只会加载 img 的图片
-
说明:
解析 HTML,遇到 img 元素,加载图片;
解析 CSS,遇到背景图片不加载;
渲染树没有 img,不渲染图片;也没有 div,不会去加载它的背景图,更不会去渲染。
3.2 容器 display: none
-
页面说明:页面上有个
div
容器,设置了display: none
;包含一个img
和 含有背景图的div
;<style> .wrapper { display: none; } .bg-wrapper { background-image: url("./blue.png"); } </style> <div class="wrapper"> <img src="./green.png" /> <div class="bg-wrapper"></div> </div>
-
图片资源加载情况:只会加载 img 的图片
-
说明:
解析 HTML,遇到 img 元素,加载图片;
解析 CSS,遇到背景图片不加载;
渲染树没有外层 div 容器,所以不会去加载子元素的背景图,更不会渲染出来。
3.3 多处使用同一张图片
-
页面说明:页面上两个
img
,还有一个含有背景图的div
,它们都用到了同一张图<style> .bg-wrapper { background-image: url("./green.png"); } </style> <img src="./green.png" /> <img src="./green.png" /> <div class="bg-wrapper"></div>
-
图片资源加载情况:只会加载图片一次
-
说明:
浏览器请求资源时,都会先判断是否有缓存,若有缓存且未过期则会从缓存中读取,不会再次请求。先加载的图片会存储到浏览器缓存中,后面再次请求同路径图片时会直接读取缓存中的图片。
3.4 未用到的背景图
-
页面说明:有两个 class,其中一个类名并未被使用到。
<style> .other { background-image: url("./blue.png"); } .bg-wrapper { background-image: url("./green.png"); } </style> <div class="bg-wrapper"></div>
-
图片资源加载情况:只会加载使用到的背景图
-
说明:
渲染树找不到一个 DOM 元素应用到这个类名,所以不会去加载它,更不会去渲染它。
3.5 伪类应用到背景图片
-
页面说明:div 在 hover 的时候改变背景图片
<style> .other { background-image: url("./blue.png"); } .bg-wrapper { background-image: url("./green.png"); } </style> <div class="bg-wrapper"></div>
-
图片资源加载情况:
hover前:只加载一个
hover后:再加载另外一个 说明:
触发 hover 前,构建渲染树过程中,遍历 DOM 树时,该元素匹配的样式规则是无 hover 状态选择器样式,因此加载对应背景图。此时没有元素匹配到hover 后的选择器样式,因此不会去加载 hover 后的背景图。
触发 hover 后,该元素匹配的是有 hover 状态选择器样式,因此加载有 hover状态选择器的背景图。