这篇文章发布于 2019年09月30日,星期一,00:20,归类于 HTML相关, JS实例。 阅读 75498 次, 今日 29 次 31 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=8981
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。
一、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技术提高下。
本文为原创文章,欢迎分享,勿全文转载,如果内容你实在喜欢,可以加入收藏夹,永不过期,而且还会及时更新知识点以及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=8981
(本篇完)
- 使用navigator.connection.downlink前端测网速 (0.449)
- 聊聊Web网页中资源加载的优先级 (0.337)
- 基于用户行为的图片等资源预加载 (0.309)
- 开源移动端元素拖拽惯性弹动以及下拉加载两个JS (0.159)
- 深入Node.compareDocumentPosition API (0.147)
- 小tip:iframe高度动态自适应 (0.135)
- HTML5 postMessage iframe跨域web通信简介 (0.135)
- iframe和HTML5 blob实现JS,CSS,HTML直接当前页预览 (0.135)
- 寥寥数行SVG实现圆环loading或倒计时效果 (0.112)
- 妙法攻略:渐变虚框及边框滚动动画的纯CSS实现 (0.112)
- 密码强度效果最佳实现一定是HTML meter元素 (RANDOM - 0.012)
值现在只有两个了吧,没有auto了
支持占位图片嘛
我也试了下,将img高度固定,或者img的父元素高固定,是有效果的,不过试了下也是加载了三屏的图片(我一张图片的父元素设置了一屏高度)
看了这篇文章 ,动手试了下,不知道哪出了问题,没有懒加载迹象(黑人问号)
贴上地址:
stackblitz.com/edit/angular-ivy-uzs3gh?file=src%2Fapp%2Fapp.component.html
浏览器有一套自己的策略。
前陣子 Chrome 的 機制有大幅度的修改。
以 4G 網路來說,原本距離螢幕約 3000px 就會載入,現在則調整到 1250px 左右;而 3G 的部分則從 4000px 修改到 2500px。
這項更新從過去的 79 版到現在最新的 85 都涵蓋在內。
詳細內容可以參考這一篇:https://web.dev/native-lazy-loading/#improved-data-savings-and-distance-from-viewport-thresholds
我的chrome 80版本的怎么还是一次性加载30个图片啊?
chrome 83版本 也是一次性加载30个图片
一次加载20张额
我的chrome83,也是一次性全部加载出来
chrome v94,一次全加载出来了
我的chrome 103怎么也是一次性全部加载出来了,哪个操作没对吗
+1,当前最新版本chrome/edge一次性加载了30张图片,firefox一开始加载了20张图片
像这样把展示图片怎么弄成懒加载,头大了
代码被吞了,就是用background设置的文章列表缩略图,这样的图片怎么加懒加载
这个目前没有API,需要JS控制。
只有图片高度确定时这功能才有用
不是,我自己测试没有写任何与高度相关的属性或者style,也会触发加载的。不过加载数量确实很迷糊,而不是控制图片元素到达视口才会加载。
如果一行几张图片,宽度变化的时候也会触发图片加载。
这功能太棒了。应该是最好的加载体验。页面滚动也不容易出现需要等待图片加载的情况(滚动速度快网速慢的时候需要等待图片加载那是不可避免的)。
自己写代码,监听 resize 即可,或者利用 IntersectionObserver 也可以。
例如本站,翻评论区翻到底跳出来一堆头像
浏览器越来越强大了,不过感觉还是没第三方库更“智能“”
张老师,我用手机微信打开的dwmo,看不到图片,只有转圈圈的loading图,是demo没有做普通浏览器的兼容吗
对的,不支持的浏览器没做兼容,这是个测试页。
佩服这种钻研精神,能一直保持着这么强大的学习动力,好赞
能理解这个api的想法,眼睛可见的图片优先加载,网络良好时尽量延迟加载,网络不好时尽量加载,尽量让体验好起来,而不是一个劲的延迟加载,体验至上~
可惜属于新特性,还不到尽情使用的时候啊~
之前也试过了,加载有点诡异的感觉
想不到浏览器原生支持图片懒加载了,很好!
「2. Lazy loading加载数量与网速有关,网速越慢,加载数量越多,但并不是线性关系。」
网速越慢,加载越多,感觉不太符合常理?按理说,网速越慢,不应该少加载一点吗?
求解惑
多加载哦,这样快速滑动才不会有图片来不及加载导致空白的场景出现。
不错,不错,研究的精神很让人学习。
国庆节快乐。