昨天我們解釋了什麼是像素密度,也介紹怎麼透過<img>
元素的srcset
屬性,為同一張圖片提供其他像素密度版本的檔案。
不過除了像素密度,我們還需要考量瀏覽裝置的尺寸。
由於圖片在不同裝置上可能會有不一樣的顯示尺寸。如果只有一種版本可以使用,可能圖片尺寸(總像素)對大螢幕裝置來說太小,或對小螢幕裝置來說太小。
雖然可以使用昨天提到的像素密度描述符提供多種版本。但是用像素密度來區分圖片尺寸,不直覺也很複雜。
假如需要對多種顯示尺寸提供多種像素密度的圖片版本,也可能會有不同版本的總像素其實一樣,只是在不同顯示尺寸下,像素密度才不同的問題。
這時候我們可以改用srcset
屬性的寬度描述符,將圖片依尺寸區分為不同版本。
srcset
與sizes
屬性,為同張圖片提供不同尺寸的版本srcset
的寬度描述符需搭配size
屬性使用不過如果單純用srcset
屬性的寬度描述符區分圖片版本,瀏覽器可能也不確定要使用哪個尺寸的圖片。
因為瀏覽器在下載圖片時,可能還沒處理好CSS設定。瀏覽器只知道瀏覽裝置目前的viewport,不確定網頁實際的版面佈局,以及圖片在這個版面佈局中要顯示的尺寸。[1]
所以使用srcset
屬性的寬度描述符時,需要搭配另一個sizes
屬性。這樣瀏覽器才能依據顯示尺寸,判斷哪個版本提供的圖片尺寸(總像素)最適合使用。
size
屬性簡介透過sizes
屬性,能夠設定圖片在不同媒體條件下的顯示尺寸。
這裡的媒體條件包括剛剛提到的viewport。關於viewport,我們在第四天有介紹過,指的是網頁在裝置上的顯示範圍,通常會以寬度來描述。
設定sizes
的屬性值時,每一種媒體條件與其對應的圖片顯示尺寸會以一組字串表示。媒體條件用括弧包起來,放在字串的開頭。圖片顯示尺寸放在結尾,以空格與前面的媒體條件相隔。
如果同時設定多個條件與尺寸,會以逗號相隔每組字串。最後一組字串表示所有媒體條件都不符合時,圖片會顯示的尺寸,所以不用寫出媒體條件。
圖片顯示尺寸以寬度來設定,規則如下:
<img>
元素本身。如同前面說的,sizes屬性與srcset屬性的寬度描述符需要一起使用,兩者缺一不可。
實際運作上,瀏覽器會先根據sizes
屬性的設定,判斷裝置目前的viewport符合哪一個媒體條件,因此圖片要用哪一個尺寸(寬度)來顯示。
接著,瀏覽器會比對srcset
的屬性值,將每一個圖片版本的寬度除以圖片顯示尺寸的寬度,得出像素密度。[2]
之後,瀏覽器會再根據其他條件,像是裝置的像素密度、瀏覽器的縮放等級,或是使用者的網路設定,判斷哪一個圖片版本最適合使用。所以最終顯示的圖片,不見得會是大小最接近顯示尺寸的那個版本。
需要注意的是,瀏覽器在判斷媒體條件時會依照設定的順序。如果目前的裝置符合前面的媒體條件,瀏覽器就會不會往下判斷有沒有其他更貼近的媒體條件。所以設定sizes
屬性時,應該以適當的順序排列這些字串。
以下由MDN提供的例子中,透過sizes
屬性設定了兩組媒體條件與圖片顯示尺寸(寬度)。同時搭配srcset
屬性,提供兩種寬度不同的圖片版本。
因為只有設定兩組條件,所以判斷圖片顯示尺寸時會以第一組的媒體條件(width <= 600px)
作為分水嶺。
如果裝置目前的viewport寬度小於等於600px,則圖片的顯示尺寸會是480px;如果大於600px,則圖片的顯示尺寸會是800px。
得到圖片顯示尺寸後,瀏覽器會依據srcset
屬性,計算出每個版本以這個尺寸顯示下的像素密度。之後再結合其他條件,判斷最終要使用哪一個版本的圖片。
即便瀏覽器不支援srcset
屬性,也因為有設定src
屬性,可以使用寬度為800px的那個版本。
<img
srcset="elva-fairy-480w.jpg 480w, elva-fairy-800w.jpg 800w"
sizes="(width <= 600px) 480px,
800px"
src="elva-fairy-800w.jpg"
alt="Elva dressed as a fairy" />
<picture>
元素,依裝置尺寸提供不同內容的圖片對於不同尺寸的裝置,除了提供同一張圖片的多個版本,有時候也需要提供不同內容的圖片。
可能圖片是以遠景拍攝,所以裡頭的人物在手機等小螢幕的裝置上看起來會太小,需要再手動放大才看得清楚。
這時候我們可以使用<picture>
元素,提供多組內容不同的圖片。讓瀏覽器針對小螢幕的裝置,載入裁切後的圖片。
<picture>
元素簡介<picture>
跟<img>
不同,不是空元素。所以在<picture>
元素裡,可以加入多個<source>
元素,同時提供不同圖片的路徑。
不過使用<picture>
時,仍然必須包括<img>
,不然不會顯示任何圖片。[3]如此也可以避免有些瀏覽器不支援<picture>
。
通常會將<img>
作為其他<source>
都不適用時的最終選項。使用時同樣需要加上alt
屬性,提供圖片的替代文字。
<source>
元素簡介跟<picture>
不同,<source>
是空元素。
放在<picture>
裡頭使用時,<source>
只能使用srcset
屬性提供圖片的檔案路徑;不過如果是在<video>
或<audio>
元素裡,<source>
反而只能使用src
提供路徑。[4]
使用<source>
元素時,通常會以media
屬性設定<source>
本身適用的條件。media
類似於sizes
屬性,但沒有指定圖片的顯示尺寸。
以srcset
屬性設定檔案路徑時,也可以使用像素密度描述符或寬度描述符,提供不同像素密度或寬度的圖片版本給瀏覽器挑選。
同樣的,如果srcset
使用了寬度描述符,就需要另外搭配sizes
屬性,兩者缺一不可。[4]
以下由MDN提供的範例,透過<picture>
提供兩張不同的圖片。
如果瀏覽裝置目前的viewport寬度大於等於800px,會使用第一個<source>
提供的大張圖片;如果小於800px,則使用第二個<source>
提供的小張圖片。
如果瀏覽器不支援<picture>
,則會使用<img>
提供的大張圖片。
<picture>
<source media="(width < 800px)" srcset="elva-480w-close-portrait.jpg" />
<source media="(width >= 800px)" srcset="elva-800w.jpg" />
<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva" />
</picture>
在另一個由規範提供的例子中,同樣提供兩張不同的圖片,不過srcset
的屬性值同時又使用了像素密度描述符。
如果瀏覽裝置目前的viewport寬度小於等於500px,符合media
設定的條件,則會使用<source>
提供的小張圖片;
如果viewport寬度大於500px,或是瀏覽器不支援<picture>
元素,則會使用<img>
提供的大張圖片。
由於使用了像素密度描述符,瀏覽器在決定用哪一張圖片後,還會再依據瀏覽裝置的像素密度,以及其他條件,判斷使用哪一個像素密度版本的圖片比較合適。
<h1>
<picture>
<source media="(max-width: 500px)" srcset="banner-phone.jpeg, banner-phone-HD.jpeg 2x">
<img src="banner.jpeg" srcset="banner-HD.jpeg 2x" alt="The Breakfast Combo">
</picture>
</h1>
今天我們介紹了怎麼依據裝置尺寸,提供不同內容的圖片,或是同張圖片不同尺寸的版本。
如果要為同一張圖片提供不同尺寸的版本,需要同時使用sizes
屬性以及srcset
屬性的寬度描述符。由前者判斷圖片的顯示尺寸,由後者區分圖片不同尺寸的版本。
針對小螢幕裝置提供尺寸較小的版本,可以提高圖片載入速度,也節省網路用量。
如果是想提供不同內容的圖片,則需使用<picture>
,與其中的<source>
與<img>
元素來達成。
假如對小螢幕裝置另外提供裁切後的圖片,就可以避免人物變得太小而看不清楚的問題。
[1]: Jason Grigsby, Responsive Images 101, Part 4: Srcset Width Descriptors
[2]: HTML Standard, Viewport-based selection
[3]: MDN, Using responsive images in HTML
[4]: MDN, <source>: The Media or Image Source element