圖片可能是因為以 <img>
元素內嵌在 HTML 中,或做為 CSS 背景圖片。本文將介紹如何延遲載入這兩種圖片。
內嵌圖片
最常見的延遲載入候選項目是 <img>
元素中使用的圖片。內嵌圖片提供三種延遲載入選項。您可以將該選項合併使用,以在各瀏覽器之間提供最佳相容性:
使用瀏覽器層級的延遲載入功能
Chrome 和 Firefox 都支援透過 loading
屬性延遲載入。
這個屬性可以新增至 <img>
元素,也可以新增至 <iframe>
元素。lazy
的值會指示瀏覽器立即載入位於可視區域的圖片,並在使用者捲動接近圖片時擷取其他圖片。
如要進一步瞭解瀏覽器支援,請參閱 MDN 瀏覽器相容性表格中的 loading
欄位。如果瀏覽器不支援延遲載入,系統會忽略這個屬性,並照常載入圖片。
對於大多數網站而言,將這項屬性新增至內嵌圖片可大幅提升效能,並讓使用者能載入可能沒捲動過的圖片。如果您有大量圖片,並想確保瀏覽器使用者不支援延遲載入功能,就必須將圖片與下方說明的方法結合。
詳情請參閱適用於網頁的瀏覽器層級延遲載入。
使用 Intersection Observer
為了替 <img>
元素執行折線延遲載入,我們會使用 JavaScript 檢查這些元素是否在可視區域。如果有,其中的 src
(有時是 srcset
) 屬性會填入所需圖片內容的網址。
如果您之前曾編寫過延遲載入程式碼,可能已使用 scroll
或 resize
等事件處理常式來完成工作。雖然這個方法在各種瀏覽器中是最相容的方法,但新式瀏覽器透過 Intersection Observer API 檢查元素可見度更有效率和效率。
Intersection Observer 比依賴各種事件處理常式的程式碼更容易使用和讀取,因為您只需要註冊觀察器就能查看元素,而不需要編寫繁瑣的元素可見度偵測程式碼。接下來只須決定元素顯示時的處理方式。假設延遲載入的 <img>
元素採用這個基本標記模式:
<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!">
因此,請特別留意以下三個相關的標記:
class
屬性,您可以在 JavaScript 中選取元素。src
屬性會參照網頁首次載入時顯示的預留位置圖片。data-src
和data-srcset
屬性是預留位置屬性,其中包含在元素進入可視區域後載入的圖片網址。
現在來看看如何在 JavaScript 中使用 Intersection Observer,透過此標記模式延遲載入圖片:
document.addEventListener("DOMContentLoaded", function() {
var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.srcset = lazyImage.dataset.srcset;
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
// Possibly fall back to event handlers here
}
});
在文件的 DOMContentLoaded
事件中,此指令碼會查詢所有具備 lazy
類別之 <img>
元素的 DOM。如果有 Intersection Observer,請建立新的觀察器,以便在 img.lazy
元素進入可視區域時執行回呼。
所有新版瀏覽器皆可使用 Intersection Observer。因此,您可以將其做為 loading="lazy"
的 polyfill,確保大多數訪客都能使用延遲載入功能。
CSS 中的圖片
雖然 <img>
標記是在網頁上使用圖片最常見的方式,但您也可以透過 CSS background-image
屬性 (和其他屬性) 叫用圖片。瀏覽器層級延遲載入不適用於 CSS 背景圖片,因此如果您有可延遲載入的背景圖片,就必須考慮其他方法。
無論 <img>
元素是否載入,CSS 圖片載入行為都是進行更多推測,建構文件和 CSS 物件模型和轉譯樹狀結構時,瀏覽器會先檢查 CSS 套用至文件的方式,然後再要求外部資源。如果瀏覽器判定含有外部資源的 CSS 規則不適用於文件目前建構中的文件,瀏覽器就不會要求該文件。
這種推測行為可以使用 JavaScript 判斷元素位於可視區域的時間,然後對該元素套用會叫用背景圖片的樣式,進而延遲在 CSS 中載入圖片。這會導致系統在需要時下載圖片,而非在初始載入時下載。舉例來說,我們可以有一個包含大型主頁背景圖片的元素:
<div class="lazy-background">
<h1>Here's a hero heading to get your attention!</h1>
<p>Here's hero copy to convince you to buy a thing!</p>
<a href="/buy-a-thing">Buy a thing!</a>
</div>
div.lazy-background
元素通常會包含部分 CSS 叫用的主頁背景圖片。不過,在這個延遲載入範例中,您可以在元素位於可視區域時,透過新增至元素的 visible
類別隔離 div.lazy-background
元素的 background-image
屬性:
.lazy-background {
background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}
.lazy-background.visible {
background-image: url("hero.jpg"); /* The final image */
}
接著,請使用 JavaScript 檢查元素是否在可視區域中 (透過 Intersection Observer!),並在 div.lazy-background
元素中加入 visible
類別,該元素會載入圖片:
document.addEventListener("DOMContentLoaded", function() {
var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));
if ("IntersectionObserver" in window) {
let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
lazyBackgroundObserver.unobserve(entry.target);
}
});
});
lazyBackgrounds.forEach(function(lazyBackground) {
lazyBackgroundObserver.observe(lazyBackground);
});
}
});
對最大內容繪製 (LCP) 的影響
延遲載入是很好的最佳化效果,可延遲載入圖片到實際需要的時間,從而減少啟動期間的整體數據用量和網路爭用情形。這麼做可以縮短圖片解碼所需的時間,縮短啟動時間,並減少主要執行緒的處理作業。
不過,如果您深入瞭解這項技術,延遲載入就可能會對網站的最大內容繪製 LCP 產生負面影響。請避免在啟動期間延遲載入可視區域中的圖片。
使用以 JavaScript 為基礎的延遲載入器時,請避免延遲載入可視區域圖片,因為這些解決方案通常會使用 data-src
或 data-srcset
屬性做為 src
和 srcset
屬性的預留位置。但問題在於,瀏覽器預先載入掃描器在啟動期間找不到圖片,導致載入延遲。
即使使用瀏覽器層級的延遲載入來延遲載入可視區域圖片,也可能會回溯。如果 loading="lazy"
套用至可視區域圖片,系統會延遲圖片,直到瀏覽器確定圖片位於可視區域中,因此會影響網頁的 LCP。
切勿延遲載入啟動時顯示在可視區域的圖片。該模式會對網站的 LCP 產生負面影響,進而讓使用者享有不佳的體驗。如果啟動時需要圖片,請不要延遲載入,在啟動時盡快載入圖片!
延遲載入程式庫
請盡可能使用瀏覽器層級的延遲載入功能,但如果您發現自己遇到無法採用的功能 (例如有一大群使用者仍依賴舊版瀏覽器),可以使用下列程式庫延遲載入圖片:
- lazysizes 是功能完整的延遲載入程式庫,可延遲載入圖片和 iframe。這個模式使用的模式與此處顯示的程式碼範例十分類似,因為該範例會自動繫結至
<img>
元素的lazyload
類別,而且您必須在data-src
和/或data-srcset
屬性中指定圖片網址,將這些內容分別替換為src
和/或srcset
屬性。它使用 Intersection Observer (您可以進行聚填入),而且還能使用多個外掛程式進行擴充,以執行延遲載入影片等操作。進一步瞭解如何使用延遲。 - vanilla-lazyload 是輕量級的選項,適用於延遲載入圖片、背景圖片、影片、iframe 和指令碼。它運用 Intersection Observer,支援回應式圖片,並支援瀏覽器層級的延遲載入功能。
- lozad.js 是另一個僅使用 Intersection Observer 的輕量選項。因此,這樣做可提供高效能,但需要經過多填處理,才能在舊版瀏覽器中使用。
- 如果需要 React 專用的延遲載入程式庫,請考慮回應延遲載入。雖然並未使用 Intersection Observer,但它針對那些習慣透過 React 開發應用程式的人員,提供熟悉的延遲載入映像檔。