圖片成效

圖片通常是網路上最龐大最常見的資源。因此,最佳化圖片能大幅提升網站效能。在大多數情況下,最佳化圖片是指傳送較少的位元組,藉此縮短網路時間,但您也可以傳送適合使用者裝置大小的圖片,藉此最佳化傳送給使用者的位元組數量。

您可以使用<img><picture> 元素,或 CSS background-image 屬性,將圖片新增至網頁。

圖片大小

使用圖片資源時,您可以執行的第一項最佳化作業,就是以正確大小顯示圖片。在本例中,「大小」是指圖片的「尺寸」。假設沒有其他變數,在 500 像素 x 500 像素的容器中顯示圖片時,最佳大小為 500 像素 x 500 像素。舉例來說,使用 1000 像素的正方形圖片,表示圖片比所需大小大兩倍。

不過,選擇適當的圖片大小涉及許多變數,因此在每種情況下選擇適當的圖片大小,都是相當複雜的任務。2010 年 iPhone 4 推出時,螢幕解析度 (640x960) 是 iPhone 3 (320x480) 的兩倍。不過,iPhone 4 的螢幕實體大小與 iPhone 3 大致相同。

如果以較高解析度顯示所有內容,文字和圖片會明顯變小,確切來說是縮小一半。而是 1 像素變成 2 個裝置像素。這就是「裝置像素比例 (DPR)」。iPhone 4 和之後推出的許多 iPhone 型號,DPR 都是 2。

以先前的例子來說,如果裝置的 DPR 為 2,且圖片顯示在 500 像素 x 500 像素的容器中,則正方形 1000 像素的圖片 (稱為固有尺寸) 現在是最佳尺寸。同樣地,如果裝置的 DPR 為 3,則 1500 像素的正方形圖片就是最佳大小。

srcset

<img> 元素支援 srcset 屬性,可指定瀏覽器可能使用的圖片來源清單。每個指定的圖片來源都必須包含圖片網址,以及寬度像素密度描述元。

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>

上述 HTML 片段使用像素密度描述元,提示瀏覽器在 DPR 為 1 的裝置上使用 image-500.png,在 DPR 為 2 的裝置上使用 image-1000.jpg,在 DPR 為 3 的裝置上使用 image-1500.jpg

雖然這些內容看似簡單明瞭,但選擇特定網頁的最佳圖片時,螢幕的 DPR 並非唯一考量。頁面的版面配置也是另一項考量因素。

sizes

如果要在所有檢視區塊中以相同的 CSS 像素大小顯示圖片,先前的解決方案就適用。在許多情況下,網頁的版面配置 (以及容器的大小) 會因使用者的裝置而異。

sizes 屬性可讓您指定一組來源大小,每個來源大小都包含媒體條件和值。sizes 屬性會以 CSS 像素為單位,說明圖片的預期顯示大小。結合 srcset 寬度描述元後,瀏覽器就能選擇最適合使用者裝置的圖片來源。

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
  sizes="(min-width: 768px) 500px, 100vw"
>

在上述 HTML 程式碼片段中,srcset 屬性會指定瀏覽器可選擇的候選圖片清單,並以半形逗號分隔。清單中的每個候選項目都包含圖片的網址,後方接著表示圖片內在寬度的語法。圖片的固有尺寸就是圖片的維度。舉例來說,描述元 1000w 表示圖片的內建寬度為 1000 像素。

瀏覽器會根據這項資訊評估 sizes 屬性中的媒體條件,並在此情況下收到指示:如果裝置的檢視區塊寬度超過 768 像素,圖片寬度就會顯示為 500 像素。在較小的裝置上,圖片會以 100vw 或完整檢視區塊寬度顯示。

瀏覽器接著會將這項資訊與 srcset 圖片來源清單合併,找出最佳圖片。舉例來說,如果使用者在螢幕寬度為 320 像素的行動裝置上,以 3 的 DPR 瀏覽網頁,圖片會以 320 CSS pixels x 3 DPR = 960 device pixels 顯示。在本範例中,最接近的圖片大小為 image-1000.jpg,其內建寬度為 1000 像素 (1000w)。

檔案格式

瀏覽器支援多種不同的圖片檔案格式。WebPAVIF 等新式圖片格式的壓縮效果可能優於 PNG 或 JPEG,因此圖片檔案大小較小,下載時間也較短。以新式格式提供圖片,可以縮短資源載入時間,進而降低最大內容繪製 (LCP)

WebP 是廣泛支援的格式,適用於所有新式瀏覽器。WebP 的壓縮效果通常比 JPEG、PNG 或 GIF 更好,且提供有損無損壓縮。即使使用有損壓縮,WebP 也支援 Alpha 管道透明度,這是 JPEG 編碼器沒有的功能。

AVIF 是較新的圖片格式,雖然支援程度不如 WebP,但瀏覽器支援程度相當不錯。AVIF 支援有損和無損壓縮,測試顯示,在某些情況下,與 JPEG 相比,AVIF 的檔案大小可縮減超過 50%。AVIF 也提供廣色域 (WCG)高動態範圍 (HDR) 功能。

壓縮

圖片壓縮分為兩種:

  1. 有損壓縮
  2. 無損壓縮

有損壓縮會透過量化降低圖片準確度,並使用色度二次取樣捨棄額外的色彩資訊。有損壓縮最適合用於高密度圖片,這類圖片通常含有大量雜訊和色彩,例如內容相似的相片或圖像。這是因為在如此細緻的圖片中,較不容易注意到有損壓縮產生的失真。不過,如果圖像包含銳利邊緣 (例如線條藝術、同樣鮮明的細節或文字),有損壓縮可能就沒那麼有效。有損壓縮可套用至 JPEG、WebP 和 AVIF 圖片。

無損壓縮會壓縮圖片,但不會遺失任何資料,因此能縮小檔案大小。無損壓縮會根據像素與相鄰像素的差異描述像素。無損壓縮適用於 GIF、PNG、WebP 和 AVIF 圖片格式。

你可以使用 SquooshImageOptim 或圖片最佳化服務壓縮圖片。壓縮時,沒有適用於所有情況的通用設定。建議您嘗試不同的壓縮等級,直到在圖片品質和檔案大小之間取得適當平衡。部分進階圖片最佳化服務可自動執行這項作業,但可能不適合所有使用者。

<picture> 元素

<picture> 元素可讓您更彈性地指定多個候選圖片:

<picture>
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image.jpg"
  >
</picture>

<picture> 元素中使用 <source> 元素時,您可以新增對 AVIF 和 WebP 圖片的支援,但如果瀏覽器不支援新式格式,則會改用相容性較高的舊版圖片格式。採用這種做法時,瀏覽器會挑選符合條件的第一個 <source> 元素。如果可以以該格式算繪圖片,就會使用該圖片。否則,瀏覽器會移至下一個指定的 <source> 元素。在上述 HTML 片段中,AVIF 格式的優先順序高於 WebP 格式,如果系統不支援 AVIF 或 WebP,則會改用 JPEG 格式。

<picture> 元素必須內嵌 <img> 元素。altwidthheight 屬性是在 <img> 上定義,且無論選取哪個 <source>,都會使用這些屬性。

<source> 元素也支援 mediasrcsetsizes 屬性。與先前的 <img> 範例類似,這些屬性會向瀏覽器指出要在不同檢視區塊中選取的圖片。

<picture>
  <source
    media="(min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

media 屬性會採用媒體條件。在前例中,裝置的 DPR 會做為媒體條件。DPR 大於或等於 1.5 的裝置會使用第一個 <source> 元素。<source> 元素會告知瀏覽器,在可視區域寬度超過 768 像素的裝置上,所選圖片候選項目會以 500 像素的寬度顯示。在較小的裝置上,這會佔用整個可視區域寬度。結合 mediasrcset 屬性,即可更精細地控管要使用的圖片。

下表說明瞭這點,其中評估了數個可視區寬度和裝置像素比例:

可視區域寬度 (像素) 1 DPR 1.5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 500.jpg 1000.jpg
480 500.jpg 500.jpg 1000.jpg 1500.jpg
560 500.jpg 1000.jpg 1000.jpg 1500.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

DPR 為 1 的裝置會下載 image-500.jpg 圖片,包括大多數桌機使用者 (他們會以 500 像素寬的外部大小查看圖片)。另一方面,DPR 為 3 的行動裝置使用者可能會下載較大的圖片,也就是 DPR 為 3 的電腦裝置所用的圖片。image-1500.jpg

<picture>
  <source
    media="(min-width: 561px) and (min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <source
    media="(max-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

在這個範例中,<picture> 元素經過調整,納入額外的 <source> 元素,以便為高 DPR 的寬螢幕裝置使用不同圖片:

可視區域寬度 (像素) 1 DPR 1.5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 1000-sm.jpg 1000-sm.jpg
480 500.jpg 500.jpg 1000-sm.jpg 1500-sm.jpg
560 500.jpg 1000-sm.jpg 1000-sm.jpg 1500-sm.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

透過這項額外查詢,您可以看到 image-1000-sm.jpgimage-1500-sm.jpg 會顯示在小型檢視區塊中。這項額外資訊可進一步壓縮圖片,因為在該大小和密度下,壓縮成果並不明顯,同時也不會影響桌上型裝置上的圖片品質。

或者,您也可以調整 srcsetmedia 屬性,避免在小型可視區域中放送大型圖片:

<picture>
  <source
    media="(min-width: 561px)"
    srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
  >
  <source
    media="(max-width: 560px)"
    srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

在上述 HTML 程式碼片段中,寬度描述元已移除,改用裝置像素比例描述元。即使裝置的 DPR 為 3,行動裝置上顯示的圖片仍會受限於 /image-500.jpg/image-1000.jpg

如何管理複雜度

使用回應式圖片時,您可能會發現每張圖片都有許多不同大小的變化版本和格式。在前例中,系統會使用各尺寸的變體,但排除 AVIF 和 WebP。您應該有多少個變體?如同許多工程問題,答案通常是「視情況而定」。

雖然您可能會想盡可能提供多種變化版本,以達到最佳效果,但每增加一個圖片變化版本都會產生費用,且會降低瀏覽器快取的效率。只有一個變體時,每位使用者都會收到相同的圖片,因此可以非常有效率地快取。

另一方面,如果變化版本很多,每個變化版本都需要另一個快取項目。如果變體的快取項目已過期,且需要從原始伺服器再次擷取圖片,伺服器成本可能會增加,效能也可能降低。

此外,HTML 文件的大小會隨著每個變化形式而增加。你可能會發現自己為每張圖片運送了數 KB 的 HTML。

根據 Accept 要求標頭放送圖片

Accept HTTP 要求標頭會告知伺服器使用者瀏覽器可接受的內容類型。伺服器可使用這項資訊提供最佳圖片格式,不會在 HTML 回應中加入額外位元組。

if (request.headers.accept) {
  if (request.headers.accept.includes('image/avif')) {
    return reply.from('image.avif');
  } else if (request.headers.accept.includes('image/webp')) {
    return reply.from('image.webp');
  }
}

return reply.from('image.jpg');

上述 HTML 片段是簡化版程式碼,您可以將其新增至伺服器的 JavaScript 後端,選擇並提供最佳圖片格式。如果要求 Accept 標頭包含 image/avif,系統就會提供 AVIF 圖片。否則,如果 Accept 標頭包含 image/webp,系統就會提供 WebP 圖片。如果這兩項條件都不成立,系統就會提供 JPEG 圖片。

您幾乎可以在任何類型的網路伺服器中,根據 Accept 要求標頭的內容修改回應。舉例來說,您可以使用 mod_rewrite,根據 Accept 標頭在 Apache 伺服器上重新編寫圖片要求。

這與圖片內容傳遞聯播網 (CDN) 的行為類似。圖片 CDN 是絕佳的解決方案,可根據使用者的裝置和瀏覽器,最佳化圖片並傳送最佳格式。

重點在於取得平衡,產生合理數量的候選圖片,並評估對使用者體驗的影響。不同圖片可能會產生不同結果,而套用至每張圖片的優化效果,取決於圖片在網頁中的大小,以及使用者使用的裝置。舉例來說,全寬主頁橫幅圖片可能需要比電子商務產品資訊頁面上的縮圖更多變化版本。

延遲載入

您可以使用 loading 屬性,在圖片顯示於檢視區塊時,指示瀏覽器延遲載入圖片。lazy 屬性值會告知瀏覽器,直到圖片位於 (或接近) 檢視區塊時,才下載圖片。這樣可以節省頻寬,讓瀏覽器優先處理轉譯可視區域中重要內容所需的資源。

decoding

decoding 屬性會告訴瀏覽器如何解碼圖片。async 值會告知瀏覽器圖片可以非同步解碼,可能縮短其他內容的轉譯時間。sync 值會告知瀏覽器圖片應與其他內容同時顯示。auto 的預設值可讓瀏覽器決定最適合使用者的設定。

圖片示範

學以致用

哪些圖片格式支援無損壓縮?

GIF。
答對了!
JPEG。
請再試一次。
.PNG。
答對了!
WebP。
答對了!
AVIF。
答對了!

哪些圖片格式支援有損壓縮?

GIF。
請再試一次。雖然 GIF 格式僅支援 256 種顏色的有限調色盤,但必須先完成有損編碼,才能轉換為 GIF。
JPEG。
答對了!
.PNG。
請再試一次。
WebP。
答對了!
AVIF。
答對了!

寬度描述元 (例如 1000w) 會向瀏覽器說明 srcset 屬性中指定的候選圖片,

圖片的外部寬度,也就是在樣式套用至網頁後,圖片在版面配置中的尺寸。
請再試一次。
圖片的內建寬度,也就是圖片本身的尺寸。
答對了!

sizes 屬性會向瀏覽器說明套用該屬性的 <img> 元素?

邏輯:根據使用者目前檢視區塊的尺寸,表示應載入 <img> 元素 srcset 中指定的候選項目。
答對了!
要從 <img> 元素的 srcset 屬性載入的圖片內建寬度。
請再試一次。

下一項:影片成效

圖片可能是網路上最常見的媒體類型,但就成效而言,您需要注意的媒體類型遠不只圖片。影片是網路上另一種常見的媒體類型,也有自己的成效考量。在本課程的下一個單元中,我們將探討影片最佳化的一些技巧,以及如何有效率地載入影片。