Image loading and rendering rules

This article studies the loading and rendering timing of image resources in the page, so that we can better manage image resources, avoid unnecessary traffic and improve user experience.

Browser Workflow

To study the loading and rendering of image resources, we first need to understand how browsers work. Take the workflow of the Webkit engine as an example:

 

 

As can be seen from the above figure, the browser performs the following operations after loading an HTML page:

  • Parse HTML —> Build DOM tree

  • Load style -> Parse style -> Build style rule tree

  • Load javascript —> execute javascript code

  • Match the DOM tree with the style rule tree to build the rendering tree

  • Calculate element position for layout

  • draw

From the above figure, we can't intuitively see when the image resource starts to be loaded. The following figure shows the timing of image loading and rendering:

  • Parse HTML [Encounter tags to load images] —> Build DOM tree

  • Load style -> Parse style [do not load when encountering background image links] -> Build style rule tree

  • Load javascript —> execute javascript code

  • Match the DOM tree and the style rule tree to build a rendering tree [load the background image on the rendering tree]

  • Calculate element position for layout

  • Draw [Start rendering picture]

Image loading and rendering rules

Not all label images and stylesheet background images on the page are loaded.

display:none

<style>

.img-purple {

   background-image: url(../image/purple.png);

}

</style>

<imgsrc="../image/pink.png"style="display:none">

<divclass="img-purple"style="display:none"></div>

The image resource request is as follows:



 

For elements with the display:none attribute set, the image will not be rendered, but will be loaded.

principle

When building a render tree by matching the DOM tree with the style rule tree, all attributes on the renderable element (such as the display:none attribute and the background-image attribute) are combined into the render tree.

The image on the label element is loaded when parsing the render tree, and the background image is loaded when the element has a background-image attribute.

When a display:none attribute is found on an element during drawing, the element position is not calculated and the element is not drawn.

<style>

.img-yellow {

   background-image: url(../image/yellow.png);

}

</style>

<divstyle="display:none">

   <imgsrc="../image/red.png">

   <divclass="img-yellow"></div>

</div>

The image resource request is as follows:



 

If the child element of the element with display:none attribute is set, the background image in the style sheet will not be rendered and will not be loaded; and the image of the label will not be rendered, but will be loaded.

principle

As mentioned above, when building a rendering tree, only renderable elements are output to the rendering tree, which means that there are non-renderable elements. When matching the DOM tree and the style rule tree, if it is found that an element has display on its attribute :none, the browser will consider the child elements of this element to be non-renderable, so the child elements of this element will not be output to the rendering tree.

When the render tree is parsed, there are no child elements of the element with the display:none attribute set on the render tree, so the images of the child elements of this element will not be loaded.

When drawing, because there is no child element of the element with the display:none attribute set on the rendering tree, the child element of the element will not be rendered.

duplicate image

.img-blue {

   background-image: url(../image/blue.png);

}

<div class="img-blue"></div>

<img src="../image/blue.png">

<img src="../image/blue.png">

The image resource request is as follows:



 

The background image path in multiple tags or style sheets in the page is the same, and the image is loaded only once.

principle

When the browser requests a resource, it will first determine whether there is a cache. If there is a cache and it has not expired, it will be read from the cache and will not be requested again. The image loaded first will be stored in the browser cache, and when the image with the same path is requested again later, the image in the cache will be directly read.

Background image for elements that do not exist

.img-blue {

   background-image: url(../image/blue.png);

}

.img-orange{

   background-image: url(../image/orange.png);

}

<div class="img-orange"></div>

The image resource request is as follows:



 

Background images for non-existing elements will not load.

principle

Non-existing elements will not be output to the DOM tree, so there will be no non-existing elements in the rendering tree. When parsing the rendering tree, non-existing elements cannot be parsed, and pictures on non-existing elements will naturally not be loaded. won't render.

Pseudo-class background image

.img-green {

   background-image: url(../image/green.png);

}

.img-green:hover{

   background-image: url(../image/red.png);

}

<div class="img-green"></div>

The image resource request before triggering the hover is as follows:



 

The image resource request after the hover is triggered is as follows:



 

When the pseudo-class is triggered, the background image on the pseudo-class style will be loaded.

principle

Before the hover is triggered, the DOM tree and the style rule tree match the style of the no-hover state selector .img-green, so the value of the background-image attribute on the rendering tree is url(../image/green.png), parsing and rendering When the tree is loaded, green.png is loaded, and green.png is also rendered when drawing.

After the hover is triggered, because the priority of .img-green:hover is relatively high, the DOM tree matches the style rule tree with the style of the hover state selector .img-green:hover, and the value of the background-image attribute on the rendering tree is url (../image/red.png), red.png is loaded when parsing the rendering tree, and red.png is also rendered when drawing.

application

placeholder map

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

预加载

很多场景里图片是在改变或触发状态后才显示出来的,例如点击一个Tab后,一个设置display:none隐藏的父元素变为显示,这个父元素里的子元素图片会在父元素显示后才开始加载;又如当鼠标hover到图标后,改变图标图片,图片会在hover上去后才开始加载,导致出现闪一下这种不友好的体验。

在这种场景下,我们就需要把图片预加载,预加载有很多种方式:

1.若是小图标,可以合并成雪碧图,在改变状态前就把所有图标都一起加载了。 
2.使用上文讲到的,设置了display:none属性的元素,图片不会渲染出来,但会加载。把要预加载的图片加到设置了display:none的元素背景图或标签里。 
3.在javascript创建img对象,把图片url设置到img对象的src属性里。

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326662642&siteId=291194637