5

浏览器IMG图片原生懒加载loading=”lazy”实践指南

 3 years ago
source link: https://www.zhangxinxu.com/wordpress/2019/09/native-img-loading-lazy/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=8981
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

原生懒加载

一、Lazy loading Chrome 76支持啦

年初就听说Chrome浏览器的IMG图片和IFRAME框架会支持原生懒加载特性,使用loading="lazy"语法。

盼星星盼月亮,终于,兼容性表中的格子绿啦,绿色真好,Chrome76支持!

图片原生懒加载兼容性

我一看自己的浏览器,嘿嘿嘿,已经升级到最近版本,兼容性足够了,可以玩起来啦:

我Chrome浏览器版本

二、懒加载特性的研究

如果你想要让一张图片在靠近浏览器视窗的时候才加载,下面代码就可以了:

<img src="./example.jpg" loading="lazy" alt="zhangxinxu">

无需任何其他的JavaScript代码就可以实现懒加载功能。

眼见为实,您可以狠狠地点击这里:图片原生懒加载lazy loading演示demo

demo页面共有30张 180*180的垂直展示的图片。

我们打开控制台,刷新页面,可以看到加载了有17张图片,剩下的13张没有加载。

加载了17个资源

居然加载了17张图片,这个数量远远超出了自己的预估!1f632.svg

因为按照demo页面现在的布局,一屏只能显示4张图片,现在一口气加载了17张,难道是加载4屏高度以内的图片素材?

于是我把页面屏幕显示高度变小,再刷新看看,结果如下:

加载了13张图片素材

可见加载素材的个数确实和屏幕的可用高度有关,但是并不是按照屏幕高度比例来计算的,迷茫了,没办法,看看规范文档,里面是怎么说的,然而并没有找到相关信息,很可能加载的细节是浏览器厂商自己决定的。

因此,可以得到第一个结论:

1. Lazy loading加载数量与屏幕高度有关,高度越小加载数量越少,但并不是线性关系。

疑问:与网速有关?

难道与网速有关,为了快速滚动滚动条的时候有更好的体验,而不会出现空白占位?

我又把网速调慢测试了下,结果发现果然有关!1f632.svg

在慢网速环境下,加载图片数量更多了,为了避免误差,我反复对比测试,证实了这个结论:

2. Lazy loading加载数量与网速有关,网速越慢,加载数量越多,但并不是线性关系。

例如,在默认状态下,图片加载数量稳定在16个,但是,如果是Fast 3G,则加载数量稳定在21个:

21个图片资源加载

如果是Slow 3G,则加载数量稳定在29个:

Slow 3G加载29个图片资源

用户行为与加载测试

当我们滚动屏幕的时候,没有加载的图片开始按照位置依次加载了,没有任何等待和缓冲。

滚动后加载的素材

因此可以得到结论:

3. 滚动即会触发图片懒加载,不会说滚动一屏后再去加载。

另外,测试的时候还发现另外一个现象:

4. 窗口resize尺寸变化也会触发图片懒加载,当屏幕高度从小变大的时候。

例如我们把控制台从下方变到右侧,此时浏览器高度图片变高,会发现又多了几个图片请求:

浏览器控制台位置变化
resize与滚动请求

滚动记忆与跳过加载?

浏览器普通刷新的时候会记住上一次滚动的位置,如果页面之前滚动位置是在很下面,这个时候页面刷新,那么开头那些图片会不会不加载呢?

我测试了下,结果果不其然,开始的图片并不会加载,只会加载下面的图片,看来浏览器还是挺聪明的。

滚动刷新加载后面的图片

5. 根据滚动位置不同,Lazy loading会忽略头尾的图片请求。

三、语法和参数

HTML loading属性支持的值除了'lazy'还有下面这几个:

lazy 图片或框架懒加载,也就是元素资源快要被看到的时候加载。 eager 图片或框架无视一切进行加载。 auto 默认值。图片或框架基于浏览器自己的策略进行加载。

如果HTMLImageElement或者HTMLIFrameElement元素没有显式地设置loading属性或者loading属性的值不合法,则都被当作'auto'处理。

四、与JS有关的实践指南

1. 如何判断当前浏览器是否支持loading=”lazy”?

下面三种方法都可以:

var isSupportLoading = 'loading' in document.createElement('img');
var isSupportLoading = 'loading' in new Image();
var isSupportLoading = 'loading' in HTMLImageElement.prototype;

2. 如何获取loading属性值

假设<img>元素的DOM变量名是img,则该图片元素的loading属性值直接下面语法就可以获取了:

var attrLoading = img.loading;

loading属性值获取结果

如果浏览器并不支持原生的loading懒加载,则会返回undefined,例如在Firefox浏览器下:

loading属性无法获取

3. loading自定义扩展并不会覆盖

HTMLElement.prototype.loading = function () {};
img = document.querySelector('[loading]');
img.loading;

我们在HTMLElement原型上扩展一个名为loading的函数,并不会影响图片元素原生的loading属性。

Chrome下图片的loading属性还在

但是,对于不支持的浏览器,例如Firefox,则明显受到了影响:

Firefox浏览器下的图片loading

4. 如何兼容不支持的浏览器?Polyfill?

GitHub上有个项目用来兼容原生的懒加载loading属性的,项目地址:https://github.com/mfranzke/loading-attribute-polyfill

我看了下原理,是需要把图片HTML代码放在<noscript>标签中:

<noscript class="loading-lazy">
    <img
        src="example.jpg"
        loading="lazy"
        alt="zhangxinxu"
        width="250"
        height="150"
    />
</noscript>

我头上立马出现了一连串的问号,恕我愚钝,这是个锤子效果的polyfill,无JavaScript特性下表现确实符合规范,但是有JavaScript的时候,你这串代码基本上就没有实用价值,因为图片素材本身是占据尺寸大小的,与布局密切相关的,放在<noscript>标签中,占据宽高尺寸都是0,体验一团糟,完全不能接受。

唯一可行方案是HTML代码输出的时候,根据浏览器(最好JS对象判断)输出不同的HTML代码,例如支持native loading的HTML这样:

<img src="example.jpg" loading="lazy" alt="zhangxinxu" width="250" height="150">

不支持的这样:

<img data-src="example.jpg" loading="lazy" alt="zhangxinxu" width="250" height="150">

然后再使用传统的JavaScript懒加载滚动加载实现即可。

五、研究与实践结果总结

最后,总结下,原生懒加载的5个行为特性:

  1. Lazy loading加载数量与屏幕高度有关,高度越小加载数量越少,但并不是线性关系。
  2. Lazy loading加载数量与网速有关,网速越慢,加载数量越多,但并不是线性关系。
  3. Lazy loading加载没有缓冲,滚动即会触发新的图片资源加载。
  4. Lazy loading加载在窗口resize尺寸变化时候也会触发,例如屏幕高度从小变大的时候。
  5. Lazy loading加载也有可能会先加载后面的图片资源,例如页面加载时滚动高度很高的时候。

与JavaScript有关的几个行为特征:

  1. 判断浏览器是否支持原生loading,最好使用'loading' in XXX判断。
  2. 获取loading属性值可以直接img.loading;
  3. 原生loading不可写,例如HTMLImageElement.prototype.loading会报错Illegal invocation。
  4. Polyfill就是场梦,只能等浏览器支持。

还有1分钟24:00,嘿嘿嘿。

节前最后一天,赶一篇还算前沿的研究小文,以此来祝愿大家国庆节过得开心快乐,快乐开心。

对了,我的新书《CSS选择器世界》上市了,国庆回来记得买一本支持下,恩……不对,买一本让自己CSS技术提高下。

1f913.svg

(本篇完)1f44d.svg 是不是学到了很多?可以分享到微信
1f44a.svg 有话要说?点击这里


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK