Rian

嘿,日安

Web Image Optimization:網頁圖片優化:從基本概念到避免 CLS 的最佳實踐

Posted at # Front-end

圖片是網頁設計中不可或缺的元素,但不當的處理方式可能導致頁面載入速度變慢,甚至影響用戶體驗和 SEO 排名。本文將深入探討網頁圖片優化的基本概念,包括圖片格式、HTML 標籤的使用,以及如何避免 Cumulative Layout Shift(CLS)問題,提供一系列最佳實踐,幫助你打造出更快、更穩定、更高效的網站。

MIME

檔案類型可以用 MIME 表示:

  • MIME 是一種表示文件的性質和格式,通常由兩個部分組成 主類型/子類型。
  • 常見的像是:text/html、text/javascript、audio/mpeg、video/mp4、application/json、image/jpeg、image/svg+xml、image/webp 等等。
  • 應用場景:
    • HTTP Response header:通過 Content-Type 指定內容的 MIME 類型,告訴瀏覽器處理接收到的資料。
    • 瀏覽器解析:瀏覽器根據收到的 MIME 類型來解析和顯示內容,比方說是 text/html,瀏覽器會解析並渲染。
    • 文件下載:當瀏覽器下載文件,Server 通過設定的 MIME 類型,會告訴瀏覽器怎麼處理下載的文件,像是下載完要直接打開或是儲存之類的。

圖片基本概念

向量圖片與點陣圖片

數位圖片分為向量以及點陣。

常見的向量格式包含 svg、eps、ai、pdf,特性是可以無限縮放但不失真,檔案通常比較小,多以幾何圖形的方式呈現,不適合複雜的圖像。

常見的點陣格式包含 jpg、png、gif、webp、avif,特性是使用像素網格來表示圖片,適合表現複雜的圖像,在圖片放大的時候有可能出現鋸齒或失真,檔案通常比較大。

常用在網頁上的圖片格式:

  • .jpg:檔案大小相對較小、適合複雜圖形、不支援透明度,瀏覽器支援性高。
  • .png:檔案大小相對大一點、適合複雜圖形、支援透明度,瀏覽器支援性高。
  • .gif:檔案大小相對較小、色彩數量有限不適合複雜圖形、支援性高,早期唯一一個可以以動畫方式呈現的格式,瀏覽器支援性高。
  • .webp:由 google 開發的現代圖片格式,意在提供更高的壓縮性同時表現良好的品質,檔案大小相對更小、支援透明度、支援動畫、瀏覽器支援性相對低(但現在應該已經很廣泛了),同時支援有損和無損壓縮。
  • .avif:截至 2024 最新興的圖片格式,基於AV1 影片編碼技術,由 AOMedia 開發的開放標準。一樣支援透明度及動畫,在壓縮率上面比 webp 可以再小 20%。最特別是支援 HDR 以及廣色域,滿足高品質的圖片需求,但瀏覽器普及度仍然是很大的挑戰。
  • .svg:與 webp 相比,檔案大小更小,但不適合複雜圖形。在網頁上的動畫效果比點陣圖片的動畫效果來得更好,可以使用 CSS 或是 JavaScript 控制 SVG 元素,也可以支援響應式設計不失真。

適合的圖片格式

沒有最好的圖片格式,只有最適合的圖片格式。我們可以根據是否支援透明度、動畫,以及程度表示壓縮率、檔案大小、圖片品質、瀏覽器支援程度,這幾個要點來評估要使用的圖片格式。

格式透明度支援動畫支援檔案大小壓縮率圖片品質瀏覽器支援程度
JPG⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
PNG⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
GIF⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
SVG⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
WebP⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
AVIF⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

圖片使用的 Html 標籤

通常在網頁上會使用 Html 標籤來載入圖片:

<img src="image.jpg" alt="描述" width="800" height="600"
srcset="image-1.jpg 480w, image-1.jpg 880w"
sizes="(min-width: 480px) 100vw, 880px" loading="lazy">

<img>:是最基本的圖片標籤格式,用來插入單一圖片。 當中基本屬性先不談(src、width、height),比較重要是alt、 srcset、loading 與 sizes 屬性。

  • alt:表示替代文字,在圖片無法正常顯示的時候出現,這個屬性會影響網站圖片 SEO 表現。
  • srcset:可以提供多個來源,並為每個圖片來源提供寬度或像素密度的表示。
  • sizes:與 srcset 屬性一起使用,指定圖片在不同裝置條件下的顯示大小。它會告訴瀏覽器在不同裝置條件下,圖片應該占用的空間大小。
  • loading:指定圖片的載入方式,可以設定 lazy 延遲載入或是 eager 立即載入。
<picture>
<source srcset="image-1.webp" type="image/webp">
<img src="image-1.jpg" media="(min-width: 800px)">
<img src="image-2.jpg" alt="描述">
</picture>

<picture>:這個標籤屬於容器標籤,可以替同個圖片提供多個圖片來源。當中可以包覆 多個 source 標籤,最後一個必須是 img 標籤,用於 source 圖片來源都不顯示時最後的備選方案。

source 中的屬性包含 srcset、media、type。

  • srcset:與 img 中的 srcset 相同,可以包含多個圖片,以逗號區分。
  • media:用來指定的裝置大小條件。
  • type:指定圖片的 MIME 類型,用於選擇圖片格式。

Cumulative Layout Shift (CLS)

cumulative-layout-shift

這是一個用戶他因為版面位置變動的關係,導致誤觸按鈕的案例。

CLS 是一個衡量網頁視覺穩定的指標,當圖片沒有指定寬度和高度時,瀏覽器在載入圖片會重新計算頁面佈局,導致頁面元素偏移,影響用戶體驗。為了減少 CLS,建議要將圖片設定明確的寬度和高度,或是使用CSS 的 aspect-ratio 屬性來指定圖片的寬高比例,以便瀏覽器預留正確的空間。

多數工程師可能不知道,CLS 其實在 Google Search Console 中會偵測到,這會影響到網站 SEO 排序。

search-console-detect-cls

解決 CLS 的方法:

  • 設定圖片或影片的寬高,以避免產生佈局偏移。
  • 使用 CSS aspect-ratio 屬性,對於響應式圖片可以指定寬高比,就算不知道實際尺寸,也可以為圖片預留正確的空間。
  • 使用 CSS 的 contain 屬性,可以防止元素變化影響到其他元素的位置。
  • 使用 CSS 的 transform 屬性動畫,transform不會造成 CLS 偏移。
  • 預載入字體,使用<link rel="preload">,事前載入字體資源,可以減少因為字體關係導致的佈局偏移。
  • 避免動態插入內容,像是廣告、Banner,如果真的逼不得已要動態載入,需要預先留有空間。
  • 非重點資源延遲載入,當網頁剛進入時載入重要的圖片、影片等等資訊,其他次要的圖片、影片就可以延遲載入,以減少佈局偏移。
  • 監測第三方 script 的載入,確定動態載入對頁面佈局不會造成影響。

延伸問題

為什麼延遲加載非關鍵資源可以減少佈局偏移?

因為如果在一開始載入所有資源,那頁面就會因為調整資源的關係而產生佈局偏移,如果先載入關鍵資源再載入次要資源,可以先穩定整體的視覺框架。