這篇文章中,咱們將看一下新的 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