
響應式圖片怎麼做?srcset、sizes 與 picture
同一張圖片放在手機、平板和桌面版網頁上,實際需要的顯示寬度通常不一樣。如果每個裝置都下載同一張超大的原圖,畫面雖然可以正常顯示,但也會多傳輸一堆用不到的資料。
所以在 HTML 裡,可以讓瀏覽器根據目前的 viewport、裝置像素比 (DPR) 和圖片在頁面上的實際大小,選擇比較合適的圖片。常見做法主要有兩種:
- 同一張圖片只需要不同尺寸時,使用
<img>搭配srcset與sizes。 - 需要依照 viewport、圖片裁切方式或圖片格式切換時,使用
<picture>。
簡單來說,srcset 和 sizes 比較像是在提供「同一張圖片的不同尺寸」;picture 則是讓我們可以描述更多選擇條件。
同一張圖片的不同尺寸:srcset 搭配 sizes
如果手機和桌面版只是顯示同一張圖片的不同尺寸,通常先使用 <img> 就夠了。srcset 負責列出圖片候選,sizes 則描述圖片在頁面上預計占據多少 CSS 寬度,瀏覽器再根據這些資訊選擇要下載的檔案。
只使用 srcset 時,瀏覽器怎麼選圖片
先看一個只有 srcset 的例子:
<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,計算過程可以簡化成:
圖片顯示寬度 = 450 CSS px
預計需要的圖片寬度 = 450 × 1 = 450px候選圖片中,300w 不足以涵蓋這個需求,下一個 600w 才足夠,所以瀏覽器通常會選擇 apple-medium.jpg。
這裡的重點是,srcset 提供的是候選清單,並不是由 JavaScript 自己計算後指定某一個檔案。實際選擇仍然會由瀏覽器依照 DPR、網路狀況和其他載入條件判斷,因此不需要把這段邏輯另外寫一份在前端程式裡。
sizes 會告訴瀏覽器圖片實際占多寬
如果圖片在頁面上不會占滿整個 viewport,就應該提供 sizes。例如下面的設定代表:viewport 寬度在 400px 以下時,圖片大約占 80vw;其他情況則占 50vw。
<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:
圖片顯示寬度 = 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 圖片在桌面版可以使用橫向大圖,讓人物位在畫面右側;到了手機版,如果直接把這張橫圖縮小,人物可能會變得太小,或是重要內容被擠到邊邊。這時可以另外準備一張直向裁切的圖片,把人物保留在比較適合手機閱讀的位置:
<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:
<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:
<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> 會比較清楚。