这篇文章中,咱们将看一下新的 loading
属性,它将原生 <img>
和 <iframe>
延迟加载到网页上!对好奇的人来讲,这里有一个实际的预览:javascript
<img src="celebration.jpg" loading="lazy" alt="..." />
<iframe src="video-player.html" loading="lazy"></iframe>
复制代码
咱们但愿在 Chrome 75 中提供 loading
支持并深刻研究这个功能,不久以后发布。在那以前,让咱们深刻挖掘 loading
是怎么做用的。html
浏览器页面常常包含大量图片,这会致使网络数据使用、页面膨胀和页面加载速度等问题。这些图片大多处于屏幕以外,须要用户滚动页面才能看到。java
准确的说,为了限制屏幕以外的图片对页面加载速度的影响,开发者须要用 JavaScript 包(例如 LazySizes)去延迟抓取这些屏幕以外的图片数据直至用户滚动靠近。git
一个页面加载 211 张图片,没有延迟加载的例子抓取了 10MB 的图片数据。延迟加载的版本(使用 LazySizes)只先加载了 250KB 图片数据,其它图片等用户滚动接近时才会抓取。github
若是浏览器能够为你避免加载屏幕以外的图片?这会帮助视野里的内容加载得更快,减小总体网络数据使用,减小低端设备内存使用。我很高兴去分享很快会成为可能的 images 和 iframes 新属性 loading
。web
loading
属性容许一个浏览器去延迟加载屏幕以外的 images 和 iframes 直到用户滚动靠近。loading
支持三种值:ajax
不声明这个属性至关于设置 loading=auto
。chrome
<img>
和 <iframe>
标签的 loading
属性正在做为浏览器标准的一部分被处理。浏览器
loading
属性做用于 <img>
标签(至关于 srcset
和 <picture>
)和 <iframe>
标签。bash
<!-- Lazy-load an offscreen image when the user scrolls near it -->
<img src="unicorn.jpg" loading="lazy" alt=".."/>
<!-- Load an image right away instead of lazy-loading -->
<img src="unicorn.jpg" loading="eager" alt=".."/>
<!-- Browser decides whether or not to lazy-load the image -->
<img src="unicorn.jpg" loading="auto" alt=".."/>
<!-- Lazy-load images in <picture>. <img> is the one driving image loading so <picture> and srcset fall off of that -->
<picture>
<source media="(min-width: 40em)" srcset="big.jpg 1x, big-hd.jpg 2x">
<source srcset="small.jpg 1x, small-hd.jpg 2x">
<img src="fallback.jpg" loading="lazy">
</picture>
<!-- Lazy-load an image that has srcset specified -->
<img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36em) 33.3vw, 100vw" alt="A rad wolf" loading="lazy">
<!-- Lazy-load an offscreen iframe when the user scrolls near it -->
<iframe src="video-player.html" loading="lazy"></iframe>
复制代码
“用户滚动到附近时”的确切启发方式留给浏览器。通常来讲,咱们的但愿是在进入视野以前浏览器开始提取延迟加载的 images 和 iframes。这将增长图像或 iframe 在用户滚动到它们时完成加载的更改。
提示:我建议咱们将其命名为 loading
属性,由于它的命名相似于 decoding
属性。之前的提议,相似于 lazyload
没法归纳咱们须要支持的多个属性值(lazy
、eager
和 auto
)。
咱们一直在考虑可以为延迟加载提供抓取和应用 JavaScript 库的重要性。支持以下对 loading
的功能检测:
<script> if ('loading' in HTMLImageElement.prototype) { // Browser supports `loading`.. } else { // Fetch and apply a polyfill/JavaScript library // for lazy-loading instead. } </script>
复制代码
提示:您还能将 loading
用做渐进加强。支持这个属性的浏览器能根据 loading=lazy
获取最新延迟加载的行为,而不支持该属性的浏览器仍然会加载图片。
若是对延迟加载的跨浏览器支持很重要,那么若是你在标记中使用 <img src="unicorn.png" loading="lazy" />
,光是对功能检测和延迟加载库是不够的。
标记中须要使用一些例如 <img data-src=unicorn.png />
(而不是 src
, srcset
或者 <source>
)去避免触发不支持新属性的浏览器的马上加载。JavaScript 能够根据是否支持 loading
和加载库更改成正确的属性。你能够认为这是一个混合延迟加载。
下面一个是混合延迟加载的例子。
<img>
标签。data-src 属性将会破坏预先加载扫描程序,因此咱们想要避免它出如今视野区域的任何内容中。<!-- Let's load this in-viewport image normally -->
<img src="hero.jpg" alt=".."/>
<!-- Let's lazy-load the rest of these images -->
<img data-src="unicorn.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="cats.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="dogs.jpg" loading="lazy" alt=".." class="lazyload"/>
<script> if ('loading' in HTMLImageElement.prototype) { const images = document.querySelectorAll("img.lazyload"); images.forEach(img => img.src = img.dataset.src); } else { // Dynamically import the LazySizes library let script = document.createElement("script"); script.async = true; script.src = "https://cdnjs.cloudflare.com/ajax/libs/lazysizes/4.1.8/lazysizes.min.js"; document.body.appendChild(script); } </script>
复制代码
如下是上述的替代写法,依赖于动态导入来执行相同的回退库的抓取。
<!-- Let's load this in-viewport image normally -->
<img src="hero.jpg" alt=".."/>
<!-- Let's lazy-load the rest of these images -->
<img data-src="unicorn.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="cats.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="dogs.jpg" loading="lazy" alt=".." class="lazyload"/>
<script> (async () => { if ('loading' in HTMLImageElement.prototype) { const images = document.querySelectorAll("img.lazyload"); images.forEach(img => img.src = img.dataset.src); } else { // Dynamically import the LazySizes library const lazySizesLib = await import('/lazysizes.min.js'); // Initiate LazySizes (reads data-src & class=lazyload) lazySizes.init(); // lazySizes works off a global. } })(); </script>
复制代码
Andrea Verlicchi 有一篇关于 混合延迟加载 的好文章,值得一读。
A loading=lazy demo featuring exactly 100 kitten pics 能够用,试试看。
咱们强烈建议在 loading 属性成为稳定版本以前不要在生产环境中使用。
去 chrome://flags
,打开 “Enable lazy frame loading” 和 “Enable lazy image loading” 标签,而后重启 Chrome。
Chrome 的延迟加载开发不只基于当前滚动的位置有多接近,还关系链接速度。对于不一样的链接速度,延迟加载帧和图像加载距离视口阈值是硬编码的,可是能够经过命令行覆盖。下面是一个覆盖图像延迟加载视口阈值的例子:
canary --user-data-dir="$(mktemp -d)" --enable-features=LazyImageLoading --blink-settings=lazyImageLoadingDistanceThresholdPxUnknown=5000,lazyImageLoadingDistanceThresholdPxOffline=8000,lazyImageLoadingDistanceThresholdPxSlow2G=8000,lazyImageLoadingDistanceThresholdPx2G=6000,lazyImageLoadingDistanceThresholdPx3G=4000,lazyImageLoadingDistanceThresholdPx4G=3000 'https://mathiasbynens.be/demo/img-loading-lazy'
复制代码
上述命令对应于默认配置。仅当滚动位置在图片的 400 像素之内时,才将全部的值变为 400 才开始延迟加载。下面咱们还将看到 1 像素的变化(本文前面的视频使用):
canary --user-data-dir="$(mktemp -d)" --enable-features=LazyImageLoading --blink-settings=lazyImageLoadingDistanceThresholdPxUnknown=1,lazyImageLoadingDistanceThresholdPxOffline=1,lazyImageLoadingDistanceThresholdPxSlow2G=1,lazyImageLoadingDistanceThresholdPx2G=1,lazyImageLoadingDistanceThresholdPx3G=1,lazyImageLoadingDistanceThresholdPx4G=1 'https://mathiasbynens.be/demo/img-loading-lazy'
复制代码
随着配置在将来的几周内稳定,咱们的配置有可能会发生变化.
Chrome 开发细节就是它在页面加载的时候只抓取了 2KB 的图片数据。若是服务器支持范围请求,那么前 2KB 可能会包含图片尺寸。这使得咱们能够生成或者展现一个具备一样尺寸的占位符。前 2KB 也有可能包含像字体那样的整个图像。
当用户可以看见它们的时候,Chrome 抓取了剩下的图片字节。Chrome DevTools 的一个警告就是延迟加载会致使:
一个完美的世界里,你不须要依赖客户端 JavaScript 功能检测来决定是否须要加载一个回调库——你应该在响应包含 JavaScript 延迟加载库的 HTML 以前处理。客户端提示能够启用此类检查。
给 <img loading>
一个延伸,让咱们知道你是怎么想的。我对人们如何发现跨浏览器故事和其余边缘状况特别感兴趣。咱们但愿在这个夏天的 Chrome 76 上发布 loading
属性。
With thanks to Simon Pieters, Yoav Weiss and Mathias Bynens for their feedback. A large thanks to Ben Greenstein, Scott Little, Raj T and Houssein Djirdeh for their work on LazyLoad.
Last updated May 7th, 2019