Web图片资源的加载与渲染时机
此文研究页面中的图片资源的加载和渲染时机,使得我们能更好的管理图片资源,避免不必要的流量和提高用户体验。
浏览器的工作流程
要研究图片资源的加载和渲染,我们先要了解浏览器的工作原理。以Webkit引擎的工作流程为例:
从上图可看出,浏览器加载一个HTML页面后进行如下操作:
解析HTML —> 构建DOM树
加载样式 —> 解析样式 —> 构建样式规则树
加载javascript —> 执行javascript代码
把DOM树和样式规则树匹配构建渲染树
计算元素位置进行布局
绘制
从上图我们不能很直观的看出图片资源从什么时候开始加载,下图标出图片加载和渲染的时机:
解析HTML【遇到
<img>标签加载图片】 —> 构建DOM树加载样式 —> 解析样式【遇到背景图片链接不加载】 —> 构建样式规则树
加载javascript —> 执行javascript代码
把DOM树和样式规则树匹配构建渲染树【遍历DOM树时加载对应样式规则上的背景图片】
计算元素位置进行布局
绘制【开始渲染图片】
图片加载与渲染规则
页面中不是所有的<img>标签图片和样式表背景图片都会加载。
display:none
<style>
.img-purple {
background-image: url(../image/purple.png);
}
</style>
<img src="../image/pink.png" style="display:none">
<div class="img-purple" style="display:none"></div>
图片资源请求如下:
设置了display:none属性的元素,图片不会渲染出来,但会加载。
原理
把DOM树和样式规则树匹配构建渲染树时,只会把可见元素和它对应的样式规则结合一起产出到渲染树,这就意味有不可见元素,当匹配DOM树和样式规则树时,若发现一个元素的对应的样式规则上有display:none,浏览器会认为该元素是不可见的,因此不会把该元素产出到渲染树上。
上面代码中,当解析HTML时会加载<img>标签元素上的图片。
当把DOM树和样式规则树匹配构建渲染树时,遍历DOM树上的元素,发现元素对应的样式规则上有background-image属性时会加载背景图片,但是因为这个元素是不可见元素(对应的样式规则上有diaplay:none),不会把该元素和它对应的样式规则产出到渲染树。
当绘制时因为渲染树上没有该元素,因此不会绘制该元素的背景图片。
<style>
.img-yellow {
background-image: url(../image/yellow.png);
}
</style>
<div style="display:none">
<img src="../image/red.png">
<div class="img-yellow"></div>
</div>
图片资源请求如下:
设置了display:none属性元素的子元素,样式表中的背景图片不会渲染出来,也不会加载;而<img>标签的图片不会渲染出来,但会加载。
原理
正如上面所说的,当匹配DOM树和样式规则树时,若发现元素的对应的样式规则上有display:none,浏览器会认为该元素的子元素是不可见的,因此不会把该元素的子元素产出到渲染树上。
当构建渲染树遇到了设置了display:none属性的不可见元素时,不会继续遍历不可见元素的子元素,因此不会加载该元素中子元素的背景图片。
当绘制时也因为渲染树上没有设置了display:none属性元素,也没有改元素的子元素,因此该元素中子元素的背景图片不会渲染出来。
重复图片
.img-blue {
background-image: url(../image/blue.png);
}
<div class="img-blue"></div>
<img src="../image/blue.png">
<img src="../image/blue.png">
图片资源请求如下:
页面中多个<img>标签或样式表中的背景图片图片路径是同一个,图片只加载一次。
原理
浏览器请求资源时,都会先判断是否有缓存,若有缓存且未过期则会从缓存中读取,不会再次请求。先加载的图片会存储到浏览器缓存中,后面再次请求同路径图片时会直接读取缓存中的图片。
不存在元素的背景图片
.img-blue {
background-image: url(../image/blue.png);
}
.img-orange{
background-image: url(../image/orange.png);
}
<div class="img-orange"></div>
图片资源请求如下:
不存在元素的背景图片不会加载。
原理
不存在的元素不会产出到DOM树上,构建渲染树过程中遍历DOM树时无法遍历不存在的元素,因此不会加载图片,也不会产出到渲染树上。当解析渲染树时无法解析不存在的元素,不存在的元素自然也不会渲染。
伪类的背景图片
.img-green {
background-image: url(../image/green.png);
}
.img-green:hover{
background-image: url(../image/red.png);
}
<div class="img-green"></div>
触发hover前的图片资源请求如下:
触发hover后的图片资源请求如下:
当触发伪类的时候,伪类样式上的背景图片才会加载。
原理
触发hover前,构建渲染树过程中,遍历DOM树时,该元素匹配的样式规则是无hover状态选择器.img-green的样式,因此加载无hover状态选择器.img-green的样式上green.png图片。该元素是可见元素,因此会被产出到渲染树上,绘制时渲染的也是green.png。
触发hover后,因为.img-green:hover的优先级比较高,构建新的渲染树过程中,该元素匹配的是有hover状态选择器,因此加载有hover状态选择器.img-green:hover的样式上的red.png图片。该元素是可见元素,因此会被产出到渲染树上,绘制时渲染的也是red.png。
应用
占位图
当使用样式表中的背景图片作为占位符时,要把背景图片转为base64格式。这是因为背景图片加载的顺序在<img>标签后面,背景图片可能会在<img>标签图片加载完成后才开始加载,达不到想要的效果。
预加载
很多场景里图片是在改变或触发状态后才显示出来的,例如点击一个Tab后,一个设置display:none隐藏的父元素变为显示,这个父元素里的子元素图片会在父元素显示后才开始加载;又如当鼠标hover到图标后,改变图标图片,图片会在hover上去后才开始加载,导致出现闪一下这种不友好的体验。
在这种场景下,我们就需要把图片预加载,预加载有很多种方式:
若是小图标,可以合并成雪碧图,在改变状态前就把所有图标都一起加载了。
使用上文讲到的,设置了display:none属性的元素,图片不会渲染出来,但会加载。把要预加载的图片加到设置了
display:none的元素背景图或<img>标签里。在javascript创建img对象,把图片url设置到img对象的src属性里。
欢迎关注:Leechikit
原文链接:segmentfault.com到此本文结束,欢迎提问和指正。
写原创文章不易,若本文对你有帮助,请点赞、推荐和关注作者支持。
Web图片资源的加载与渲染时机的更多相关文章
- 浏览器加载和渲染HTML的过程(标准定义的过程以及现代浏览器的优化)
先看一下标准定义的浏览器渲染过程(网上找的): 浏览器打开网页的过程 用户第一次访问网址,浏览器向服务器发出请求,服务器返回html文件: 浏览器开始载入html代码,发现 head 标签内有一个 l ...
- web.xml的加载过程配置详解
一:web.xml加载过程 简单说一下,web.xml的加载过程.当我们启动一个WEB项目容器时,容器包括(JBoss,Tomcat等).首先会去读取web.xml配置文件里的配置,当这一步骤没有 ...
- Java Web应用的加载过程
在介绍Spring IoC和MVC的加载前,用这篇小文章简单地记录下,最简单的web应用的加载过程. 一.从最简单的web应用出发 使用Eclipse直接创建一个Dynamic Web Project ...
- web.xml文件加载顺序
1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Servl ...
- 浏览器加载和渲染html的顺序
前阵子,在组内给大家做了一次关于“浏览器加载和渲染HTML的顺序”的分享,这里再总结一下吧. AD:干货来了,不要等!WOT2015 北京站演讲PPT开放下载! 1.浏览器加载和渲染html的顺序 浏 ...
- web.xml 的加载过程
初始化过程: 在启动Web项目时,容器(比如Tomcat)会读web.xml配置文件中的两个节点<listener>和<contex-param>. 接着容器会创建一个Serv ...
- Android学习笔记之BitmapFactory.Options实现图片资源的加载...
PS:小项目总算是做完了...历经20多天...素材,设计,以及实现全由自己完成...心力憔悴啊...该写写博客记录一下学习到的东西了... 学习内容: 1.使用BitmapFactory.Optio ...
- Web Service无法加载协定为“ServiceReference1.xxxxxx”的终结点配置部分,因为找到了该协定的多个终结点配置。请按名称指示首选的终结点配置部分
Web Service 无法加载协定为“ServiceReference1.xxxxxx”的终结点配置部分,因为找到了该协定的多个终结点配置.请按名称指示首选的终结点配置部分 原因是在web.co ...
- web.xml 配置 加载顺序
web.xml 的加载顺序是:context-param -> listener -> filter -> servlet . 过滤器执行顺序是根据filter-mapping ,不 ...
随机推荐
- “Spring Boot+Marklogic实战应用(1)”
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议.本文链接:http://www.blbk.info Spring Boot+Marklogic应用 摘要: 在前一节的介绍,相信 ...
- svn http
yum install -y httpd subversion mod_dav_svn mkdir -p /var/lib/svn cd /var/lib/svn svnadmin create de ...
- PAT甲级——1009 Product of Polynomials
PATA1009 Product of Polynomials Output Specification: For each test case you should output the produ ...
- LIS 问题 二分查找优化
按n=5,a-{4,2,3,1,5}为例 dp的值依次是: INF INF INF INF INF 4 INF INF INF INF 2 INF INF INF INF 2 ...
- python学习笔记(12)常用模块
一.模块.包 什么是模块? 模块实质上就是一个python文件,它是用来组织代码的,意思就是说把python代码写到里面,文件名就是模块的名称,test.py test就是模块名称. 什么是包? 包, ...
- java 的ConcurrentHashMap底层数据结构
集合是编程中最常用的数据结构.而谈到并发,几乎总是离不开集合这类高级数据结构的支持.比如两个线程需要同时访问一个中间临界区(Queue),比如常会用缓存作为外部文件的副本(HashMap).这篇文章主 ...
- centos 中文乱码解决办法2
特别注意:vm10自带虚拟机共享工具,自动识别utf-8格式的中文文件内容 下面步骤摘自网络: 两种方案其实差不多,这里提供两个文件的下载地址,免得去网上搜这两个文件了: fonts-chinese- ...
- highcharts 柱状图在柱子顶部显示y轴数据
var plotOptions={ column:{ //borderColor: "#CCCC66",//边框 shadow: true, //阴影 dataLabels:{ / ...
- mybatis generator 使用教程(生成带注释的实体类)
引言: 最近的一个项目,由于数据库表巨多,导致需要创建N多个java实体.dao.mapper.xml映射文件,如果均使用纯手工编写,无疑需要耗费大量时间和精力.于是上网学习了mybatis gene ...
- [LC] 104. Maximum Depth of Binary Tree
Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...