web图片加载与渲染时机

前言

管理好网页的图片资源,可以避免不必要的流量和提高用户体验。

浏览器的工作流程

要研究图片资源的加载,就不得不先熟悉浏览器的工作原理,下面这张图可以很清晰的说明
image

从上图可看出,浏览器加载一个HTML页面后进行如下操作(详细解释图片资源渲染):

  • 解析HTML(遇到img标签加载图片) —> 构建DOM树
  • 加载css —> 解析css(遇到背景图片链接不加载) —> 构建css树
  • 加载js代码 —> 执行js代码
  • 把DOM树和css树匹配构建渲染树(遍历DOM树时加载对应样式规则上的背景图片)
  • 计算元素位置进行布局
  • 绘制(开始渲染图片)

图片加载与渲染规则

了解了浏览器的工作流程,现在来说说图片的加载和渲染,并不是所有的img标签图片和样式表背景图片都会加载

重复图片

1
2
3
4
5
6
.img-bg {
background: url(./demo.png);
}
<div class="img-bg"></div>
<img src="./demo.png">
<img src="./demo.png">

页面中多个img标签或样式表中的背景图片图片路径是同一个,图片只加载一次。
原因:浏览器请求资源时,都会先判断是否有缓存,若有缓存且未过期则会从缓存中读取,不会再次请求。先加载的图片会存储到浏览器缓存中,后面再次请求同路径图片时会直接读取缓存中的图片。

设置display: none的图片

1
<img src="./demo1.png" style="display: none;">

设置了display:none属性的元素,图片不会渲染出来,但会加载。
原因:在解析HTML时,遇到img标签就加载图片,DOM树和样式规则树匹配构建渲染树时,只会把可见元素和它对应的样式规则结合一起产出到渲染树

1
2
3
4
5
6
7
8
9
<style>
.img {
background: url(./demo.png);
}
</style>
<div style="display:none">
<img src="./demo1.png">
<div class="img"></div>
</div>

如果父元素设置了display:none属性,那么子元素样式表中的背景图片不会渲染出来,也不会加载;而img标签的图片不会渲染出来,但会加载。
原因:在解析HTML时,遇到img标签就加载图片,当构建渲染树遇到了设置了display:none属性的不可见元素时,不会继续遍历不可见元素的子元素,因此不会加载该元素中子元素的背景图片

伪类的背景图片

1
2
3
4
5
6
7
.img {
background: url(./domo.png);
}
.img:hover{
background: url(./demo1.png);
}
<div class="img"></div>

当触发伪类的时候,伪类样式上的背景图片才会加载。
原因:触发hover前,构建渲染树过程中,遍历DOM树时,该元素匹配的样式规则是无hover状态选择器.img的样式;触发hover后,因为.img:hover的优先级比较高,构建新的渲染树过程中,会加载伪类的背景图片。

不存在元素的背景图片

1
2
3
4
.img111 {
background: url(./domo.png);
}
<div class="img"></div>

不存在元素的背景图片不会加载。
原因:不存在的元素不会产出到DOM树上,构建渲染树过程中遍历DOM树时无法遍历不存在的元素,因此不会加载图片,也不会产出到渲染树上。

应用场景

占位图

当使用样式表中的背景图片作为占位符时,要把背景图片转为base64格式。这是因为背景图片加载的顺序在img标签后面,背景图片可能会在img标签图片加载完成后才开始加载,达不到想要的效果。

预加载

  • 使用上文讲到的,设置了display:none属性的元素,图片不会渲染出来,但会加载。把要预加载的图片加到设置了display:none的元素背景图或img标签里。
  • 在javascript创建img对象,把图片url设置到img对象的src属性里。
感谢支持,我会不断进步