一、Lazy loading Chrome 76支持啦
年初就听说Chrome浏览器的IMG图片和IFRAME框架会支持原生懒加载特性,使用loading="lazy"
语法。
盼星星盼月亮,终于,兼容性表中的格子绿啦,绿色真好,Chrome76支持!
我一看自己的浏览器,嘿嘿嘿,已经升级到最近版本,兼容性足够了,可以玩起来啦:
二、懒加载特性的研究
如果你想要让一张图片在靠近浏览器视窗的时候才加载,下面代码就可以了:
<img src="./example.jpg" loading="lazy" alt="zhangxinxu">
无需任何其他的JavaScript代码就可以实现懒加载功能。
眼见为实,您可以狠狠地点击这里:图片原生懒加载lazy loading演示demo
demo页面共有30张 180*180的垂直展示的图片。
我们打开控制台,刷新页面,可以看到加载了有17张图片,剩下的13张没有加载。
居然加载了17张图片,这个数量远远超出了自己的预估!
因为按照demo页面现在的布局,一屏只能显示4张图片,现在一口气加载了17张,难道是加载4屏高度以内的图片素材?
于是我把页面屏幕显示高度变小,再刷新看看,结果如下:
可见加载素材的个数确实和屏幕的可用高度有关,但是并不是按照屏幕高度比例来计算的,迷茫了,没办法,看看规范文档,里面是怎么说的,然而并没有找到相关信息,很可能加载的细节是浏览器厂商自己决定的。
因此,可以得到第一个结论:
1. Lazy loading加载数量与屏幕高度有关,高度越小加载数量越少,但并不是线性关系。
疑问:与网速有关?
难道与网速有关,为了快速滚动滚动条的时候有更好的体验,而不会出现空白占位?
我又把网速调慢测试了下,结果发现果然有关!
在慢网速环境下,加载图片数量更多了,为了避免误差,我反复对比测试,证实了这个结论:
2. Lazy loading加载数量与网速有关,网速越慢,加载数量越多,但并不是线性关系。
例如,在默认状态下,图片加载数量稳定在16个,但是,如果是Fast 3G,则加载数量稳定在21个:
如果是Slow 3G,则加载数量稳定在29个:
用户行为与加载测试
当我们滚动屏幕的时候,没有加载的图片开始按照位置依次加载了,没有任何等待和缓冲。
因此可以得到结论:
3. 滚动即会触发图片懒加载,不会说滚动一屏后再去加载。
另外,测试的时候还发现另外一个现象:
4. 窗口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
懒加载,则会返回undefined
,例如在Firefox浏览器下:
3. loading自定义扩展并不会覆盖
例如:
HTMLElement.prototype.loading = function () {}; img = document.querySelector('[loading]'); img.loading;
我们在HTMLElement原型上扩展一个名为loading
的函数,并不会影响图片元素原生的loading
属性。
但是,对于不支持的浏览器,例如Firefox,则明显受到了影响:
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个行为特性:
- Lazy loading加载数量与屏幕高度有关,高度越小加载数量越少,但并不是线性关系。
- Lazy loading加载数量与网速有关,网速越慢,加载数量越多,但并不是线性关系。
- Lazy loading加载没有缓冲,滚动即会触发新的图片资源加载。
- Lazy loading加载在窗口resize尺寸变化时候也会触发,例如屏幕高度从小变大的时候。
- Lazy loading加载也有可能会先加载后面的图片资源,例如页面加载时滚动高度很高的时候。
与JavaScript有关的几个行为特征:
- 判断浏览器是否支持原生loading,最好使用
'loading' in XXX
判断。 - 获取loading属性值可以直接img.loading;
- 原生loading不可写,例如HTMLImageElement.prototype.loading会报错Illegal invocation。
- Polyfill就是场梦,只能等浏览器支持。
以上~
还有1分钟24:00,嘿嘿嘿。
节前最后一天,赶一篇还算前沿的研究小文,以此来祝愿大家国庆节过得开心快乐,快乐开心。
对了,我的新书《CSS选择器世界》上市了,国庆回来记得买一本支持下,恩……不对,买一本让自己CSS技术提高下。