Skip to content

瀏覽器根據圖片尺寸候選、viewport、DPR、裁切情境與格式支援選出適合手機和桌面的圖片

響應式圖片怎麼做?srcset、sizes 與 picture ​

同一張圖片放在手機、平板和桌面版網頁上,實際需要的顯示寬度通常不一樣。如果每個裝置都下載同一張超大的原圖,畫面雖然可以正常顯示,但也會多傳輸一堆用不到的資料。

所以在 HTML 裡,可以讓瀏覽器根據目前的 viewport、裝置像素比 (DPR) 和圖片在頁面上的實際大小,選擇比較合適的圖片。常見做法主要有兩種:

  • 同一張圖片只需要不同尺寸時,使用 <img> 搭配 srcset 與 sizes。
  • 需要依照 viewport、圖片裁切方式或圖片格式切換時,使用 <picture>。

簡單來說,srcset 和 sizes 比較像是在提供「同一張圖片的不同尺寸」;picture 則是讓我們可以描述更多選擇條件。

同一張圖片的不同尺寸:srcset 搭配 sizes ​

如果手機和桌面版只是顯示同一張圖片的不同尺寸,通常先使用 <img> 就夠了。srcset 負責列出圖片候選,sizes 則描述圖片在頁面上預計占據多少 CSS 寬度,瀏覽器再根據這些資訊選擇要下載的檔案。

只使用 srcset 時,瀏覽器怎麼選圖片 ​

先看一個只有 srcset 的例子:

html
<img
  src="apple-small.jpg"
  srcset="apple-small.jpg 300w, apple-medium.jpg 600w, apple-large.jpg 1000w"
  alt="Apple 產品展示圖"
>

這裡的 300w、600w 和 1000w 是各個圖片候選的實際寬度,不是代表圖片一定會以這個寬度顯示。瀏覽器會先估算圖片在頁面上需要多寬,再把這個寬度乘上 DPR,得到大概要下載的圖片解析度。

當沒有提供 sizes 時,瀏覽器通常會先假設圖片的顯示寬度是 100vw。假設使用者的 viewport 寬度是 450px、DPR 是 1,計算過程可以簡化成:

text
圖片顯示寬度 = 450 CSS px
預計需要的圖片寬度 = 450 × 1 = 450px

候選圖片中,300w 不足以涵蓋這個需求,下一個 600w 才足夠,所以瀏覽器通常會選擇 apple-medium.jpg。

這裡的重點是,srcset 提供的是候選清單,並不是由 JavaScript 自己計算後指定某一個檔案。實際選擇仍然會由瀏覽器依照 DPR、網路狀況和其他載入條件判斷,因此不需要把這段邏輯另外寫一份在前端程式裡。

sizes 會告訴瀏覽器圖片實際占多寬 ​

如果圖片在頁面上不會占滿整個 viewport,就應該提供 sizes。例如下面的設定代表:viewport 寬度在 400px 以下時,圖片大約占 80vw;其他情況則占 50vw。

html
<img
  src="apple-small.jpg"
  sizes="(max-width: 400px) 80vw, 50vw"
  srcset="apple-small.jpg 300w, apple-medium.jpg 600w, apple-large.jpg 1000w"
  alt="Apple 產品展示圖"
>

假設 viewport 寬度是 450px、DPR 是 1,第一個 (max-width: 400px) 條件不符合,所以圖片的預計顯示寬度是 50vw:

text
圖片顯示寬度 = 450 × 0.5 = 225 CSS px
預計需要的圖片寬度 = 225 × 1 = 225px

這時候瀏覽器會選擇能涵蓋需求的最小候選,也就是 300w 的 apple-small.jpg。如果同樣是 450px 的 viewport,但 DPR 改成 2,預計需要的圖片寬度就會變成 450px,通常會改選 600w 的圖片。

sizes 描述的是圖片在版面上的預計顯示寬度,不是用來強制設定 CSS 寬度。因此它要和實際的 layout 對得上:如果 CSS 讓圖片占 50% 容器寬度,卻在 sizes 寫成 100vw,瀏覽器可能下載過大的檔案;反過來,如果實際圖片比 sizes 描述的更寬,就可能下載到解析度不夠的圖片。

另外,sizes 是搭配 srcset 的 w 寬度描述使用。如果 srcset 使用的是 1x、2x 這類密度描述,瀏覽器會直接依照 DPR 選擇候選,不會再用 sizes 來計算圖片寬度。

需要依條件切換圖片:使用 <picture> ​

如果不只是圖片尺寸不同,而是桌面版和手機版需要不同裁切,或是要依照瀏覽器支援度切換圖片格式,這時就可以使用 <picture>。

什麼是 art direction ​

art direction 可以先理解成「依照畫面情境切換圖片構圖」。它不是單純把同一張圖片縮小,而是替不同版面準備不同的裁切、焦點或構圖。

例如首頁的 hero 圖片在桌面版可以使用橫向大圖,讓人物位在畫面右側;到了手機版,如果直接把這張橫圖縮小,人物可能會變得太小,或是重要內容被擠到邊邊。這時可以另外準備一張直向裁切的圖片,把人物保留在比較適合手機閱讀的位置:

html
<picture>
  <source
    media="(max-width: 600px)"
    srcset="hero-mobile.jpg"
  >
  <img
    src="hero-desktop.jpg"
    alt="Apple 產品展示圖"
  >
</picture>

viewport 寬度在 600px 以下時,瀏覽器會使用手機版構圖;其他情況則使用桌面版構圖。這兩個檔案可以是同一個主題,但不一定是同一個裁切,這就是 art direction。

如果只是同一張圖片需要 300w、600w 和 1000w 等不同尺寸,圖片構圖沒有改變,就不需要使用 art direction,使用 srcset 和 sizes 會比較簡單。

依照 viewport 和 DPR 選擇圖片 ​

下面的例子會根據 viewport 寬度選擇 large、medium 或 small 版本,同一個尺寸區間內再透過 1x 和 2x 處理不同 DPR:

html
<picture>
  <source
    media="(min-width: 800px)"
    srcset="apple-large-1x.jpg 1x, apple-large-2x.jpg 2x"
  >
  <source
    media="(min-width: 500px)"
    srcset="apple-medium-1x.jpg 1x, apple-medium-2x.jpg 2x"
  >
  <img
    src="apple-small.jpg"
    alt="Apple 產品展示圖"
  >
</picture>

瀏覽器會依照 <source> 的順序檢查條件,使用第一個符合的來源:

  • viewport 為 800px 以上時,使用 large 版本。
  • viewport 為 500px 到 799px 時,使用 medium 版本。
  • viewport 小於 500px 時,沒有符合的 <source>,改用 <img> 作為 fallback。

1x 和 2x 是像素密度描述。DPR 為 1 時通常會選 1x,DPR 為 2 時通常會選 2x;不過和 srcset 一樣,最後仍會由瀏覽器依照當下條件決定實際要載入的候選。

<picture> 的順序很重要,因為符合條件的 <source> 不會全部一起使用,而是找到第一個符合的來源後就停止往下找。<img> 則不只是 fallback,也負責提供實際圖片元素和 alt 替代文字。

依照圖片格式提供 fallback ​

<picture> 也很適合用來提供現代圖片格式,並保留較通用的 JPEG 作為 fallback:

html
<picture>
  <source srcset="apple.avif" type="image/avif">
  <source srcset="apple.webp" type="image/webp">
  <img
    src="apple.jpg"
    alt="Apple 產品展示圖"
  >
</picture>

瀏覽器會先檢查 type 提供的 MIME type 是否支援。如果支援 AVIF,就會使用第一個來源;不支援時再繼續檢查 WebP,最後才使用 <img> 裡的 JPEG。這樣就能在支援新格式的瀏覽器中減少檔案大小,同時保留舊環境可以顯示的 fallback。

srcset、sizes 和 <picture> 要怎麼選 ​

實務上可以先用這個方向判斷:

  • 同一張圖片只需要提供不同寬度:使用 <img>、srcset 和 sizes。
  • 同一張圖片要依 DPR 提供 1x、2x 等版本:可以在 srcset 裡使用密度描述,或搭配 <picture> 的不同 source。
  • 手機和桌面需要不同裁切或不同構圖 (art direction):使用 <picture> 搭配 media。
  • 需要依照 AVIF、WebP 或 JPEG 等格式切換:使用 <picture> 搭配 type,並保留 <img> 作為 fallback。

簡單來說,srcset 和 sizes 解決的是「同一張圖片要下載多大的版本」;<picture> 解決的是「目前情境應該使用哪一組圖片來源」。如果只是尺寸不同,不需要為了使用 <picture> 而增加結構;如果需要 art direction 或格式 fallback,再使用 <picture> 會比較清楚。

參考資料 ​

按 Enter 或空白鍵放大圖片,按 Escape 關閉放大檢視。