聲明:此篇文章由靠譜男青年獎(jiǎng)得主根據(jù)Pearl Chen的英文文章《Built-in Browser Support for Responsive Images》進(jìn)行翻譯,整個(gè)譯文帶有我自己的理解,如果譯得不好或不對(duì)之處還請(qǐng)指點(diǎn)。
如需轉(zhuǎn)載此譯文,需注明英文出處:http://www.html5rocks.com/en/tutorials/responsive/picture-element/ 以及作者、譯者相關(guān)信息
——作者:Pearl Chen
——譯者:靠譜男青年獎(jiǎng)得主
介紹<picture>標(biāo)簽
<picture> 標(biāo)簽提供了瀏覽器原生支持的圖像資源加載方法。web開(kāi)發(fā)者們無(wú)需在使用CSS和Javascript Hacks來(lái)在響應(yīng)式設(shè)計(jì)中處理圖像,而使用這種設(shè)計(jì)方式創(chuàng)造出的產(chǎn)品的使用者們會(huì)從這個(gè)瀏覽器底層優(yōu)化的圖像資源加載方式獲益——特別是對(duì)于那些網(wǎng)絡(luò)加載速度很慢的用戶(hù)。
隨著srcset和sizes這兩個(gè)<img>標(biāo)簽的新屬性的加入,<picture>標(biāo)簽使得程序員在選擇加載圖像資源時(shí)更具靈活性。書(shū)寫(xiě)明確地的HTML標(biāo)記,讓瀏覽器去查明接下來(lái)這些適應(yīng)情況,不管是單獨(dú)使用還是和其他方法一同使用,從而更好地支持響應(yīng)式設(shè)計(jì),就愛(ài)哭愛(ài)網(wǎng)頁(yè)加載速度。加載情況有:
-
基于屏幕方向的選項(xiàng)
這是一個(gè)手機(jī)設(shè)備還是一個(gè)PC端設(shè)備?通過(guò)屏幕方向的識(shí)別來(lái)判斷載入資源圖片。

-
基于設(shè)備像素比的選項(xiàng)
這個(gè)設(shè)備是不是高分屏?要針對(duì)屏幕的高分辨率去加載更高分辨率的圖像。
-
基于視圖的選項(xiàng)
圖像是否在視圖中采用fixed布局?那么就使用視圖寬度判斷圖像動(dòng)態(tài)變化。
-
基于圖像格式的選項(xiàng)
瀏覽器是否支持其他的圖像格式?如果確實(shí)如此,我們可以選擇加載諸如webp[1]后綴的其他格式圖像。
基于屏幕方向的選項(xiàng)
這應(yīng)該是<picture>標(biāo)簽在進(jìn)行響應(yīng)式變化是最常見(jiàn)的一個(gè)使用情況。不去使用一張圖以設(shè)備寬度為標(biāo)準(zhǔn)來(lái)進(jìn)行縮放,取而代之的解決方案是使用多個(gè)圖像,他們中的每一個(gè)都是對(duì)應(yīng)平臺(tái)上最適合的尺寸。
改善了加載表現(xiàn)
當(dāng)使用<picture>或<img/>標(biāo)簽的時(shí)候,如果使用了srcset和sizes屬性,那么瀏覽器只下載那個(gè)最適合當(dāng)前使用情況的圖片,這個(gè)改進(jìn)符合瀏覽器語(yǔ)法,而且可以節(jié)省圖像緩存,改進(jìn)預(yù)加載能力。
看一個(gè)演示
事實(shí)是,網(wǎng)絡(luò)被創(chuàng)造是為了放置小貓照片的。使用<picture>標(biāo)簽我們可以去模仿小貓適應(yīng)空間的能力,無(wú)論這個(gè)空間是很大還是很小

點(diǎn)擊這個(gè)[超鏈接](http://googlechrome.github.io/samples/picture-element/

)打開(kāi)小貓,并且試著更改你顯示器的寬度來(lái)查看小貓是如何跟著瀏覽器寬度進(jìn)行適應(yīng)的。
到目前為止我們只是看了一些<piture>可以做到的一些小例子。下面來(lái)看看語(yǔ)法
<picture>語(yǔ)法
下面的這一串HTML和CSS語(yǔ)句片段就是我們?yōu)榱藢?shí)現(xiàn)上邊這個(gè)demo的所有代碼。
<style>
img {display: block; margin: 0 auto;}
</style>
<picture>
<source
media="(min-width: 650px)"
srcset="images/kitten-stretching.png">
<source
media="(min-width: 465px)"
srcset="images/kitten-sitting.png">
<img
src="images/kitten-curled.png"
alt="a cute kitten">
</picture>
看看,這里面沒(méi)有Javascript代碼,并且也沒(méi)有第三方庫(kù)。CSS語(yǔ)句僅僅是去控制圖像的放置位置,不包含設(shè)備查詢(xún)代碼。這意味著你只需要HTML就可以進(jìn)行圖片的響應(yīng)式開(kāi)發(fā)。
使用<source>標(biāo)簽
<picture>標(biāo)簽沒(méi)有自己的私有屬性,自適應(yīng)的秘密在于<picture>是被用作<source>標(biāo)簽的容器。
<source>標(biāo)簽是用來(lái)加載媒體文件,類(lèi)似于音頻和視頻,目前他開(kāi)始對(duì)圖片支持,并且加入了更多的屬性。
srcset(必須的屬性)
- 接受的參數(shù)是單獨(dú)一個(gè)圖片的文件路徑(比如
srcset = "../../kitten.jpg") - 或者是使用逗號(hào)隔開(kāi)的一個(gè)路徑列表,同時(shí)在屬性值里加上分辨率表達(dá)參數(shù)(比如:
srcset="kitten.png, kitten@2X.png 2x),1x是默認(rèn)的,所以他在表達(dá)式中是被省略的。
查看“使用分辨率表達(dá)式來(lái)組合路徑”獲得更詳細(xì)的使用方法。
media(可選屬性)
- 接受一個(gè)有效的媒體查詢(xún)語(yǔ)句,和css的
@media媒體查詢(xún)語(yǔ)句一樣(比如:media = "(max-width:30em)"或者medai = "(min-width):30em")
查看之前的"<picture>語(yǔ)法代碼模塊"了解具體使用例子
sizes(可選屬性)
接受一個(gè)單獨(dú)的寬度表達(dá)式(比如:
sizes="100vw"),或者是你可以放置一個(gè)媒體查詢(xún)語(yǔ)句和一個(gè)寬度表達(dá)式(比如:sizes="(max-width: 30em) 100vw"[2])。或者是接受一個(gè)由逗號(hào)隔開(kāi)的表達(dá)式列表(比如:`sizes="(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw - 100px)[3]),最后一個(gè)參數(shù)用作默認(rèn)設(shè)置。
查看使用"寬度表達(dá)式合并"模塊獲得使用方法。
type(可選屬性)
- 接受一個(gè)MIME type表達(dá)式(比如:
type="image/webp"或者是type="image/vnd.ms-photo"等)
查看“加載其他圖像格式”獲得更多使用方法
在最后加上<img/>標(biāo)簽
目前<img/>標(biāo)簽經(jīng)過(guò)用法升級(jí)之后也可以在<picture>標(biāo)簽內(nèi)部使用,這樣做是為了兼容不支持<picture>標(biāo)簽的瀏覽器或者是沒(méi)有<source>標(biāo)簽的情況或者是<source>表達(dá)式?jīng)]有使用的現(xiàn)實(shí)情況。<picture>標(biāo)簽內(nèi)的這個(gè)<img/>標(biāo)簽是必需的,如果你忘了加這個(gè)標(biāo)簽?zāi)敲丛陧?yè)面上什么都不會(huì)顯示,哪怕你加了完整的<source>也一樣。
在<picture>標(biāo)簽中使用<img/>標(biāo)簽來(lái)聲明默認(rèn)圖片,并且將它作為<picture>的最后一個(gè)子節(jié)點(diǎn),只有在<img/>存在的情況下<source>才會(huì)被聲明、渲染。同時(shí)不要忘了給<img/>增加alt屬性
使用分辨率表達(dá)式來(lái)組合路徑
為了保證對(duì)于高分辨率屏幕的支持,srcset屬性支持分辨率倍數(shù)定義如1x,1.5x,2x,3x。最新的srcset屬性已經(jīng)同時(shí)支持<img/>和<picture>標(biāo)簽了
下面這個(gè)例子支持了三種設(shè)備分辨率:1x,1.5x,2x:
<picture>
<source
media="(min-width: 650px)"
srcset="images/kitten-stretching.png,
images/kitten-stretching@1.5x.png 1.5x,
images/kitten-stretching@2x.png 2x">
<source
media="(min-width: 465px)"
srcset="images/kitten-sitting.png,
images/kitten-sitting@1.5x.png 1.5x
images/kitten-sitting@2x.png 2x">
<img
src="images/kitten-curled.png"
srcset="images/kitten-curled@1.5x.png 1.5x,
images/kitten-curled@2x.png 2x"
alt="a cute kitten">
</picture>
使用寬度表達(dá)式合并屬性
谷歌的web開(kāi)發(fā)最佳實(shí)踐手冊(cè)已經(jīng)涵蓋了最新的<img/>標(biāo)簽支持的sizes屬性:
當(dāng)一個(gè)圖片的大小和分辨率是未知的并且有可能是浮動(dòng)的,那么我們就很難去給他一個(gè)適應(yīng)的屬性
不去給圖片一個(gè)確切的寬度和分辨率,取而代之是給<img/>對(duì)象增加屬性,以允許瀏覽器經(jīng)過(guò)計(jì)算之后改變他的寬度,選擇最確切的一個(gè)尺寸進(jìn)行下載
下面是一個(gè)使用sizes的例子,這個(gè)圖片永遠(yuǎn)只填滿設(shè)備寬度的80%,實(shí)現(xiàn)方法是使用secset屬性來(lái)選擇160px、320px、640px、1280px的寬度:
<img src="lighthouse-160.jpg" alt="lighthouse"
sizes="80vw"
srcset="lighthouse-160.jpg 160w,
lighthouse-320.jpg 320w,
lighthouse-640.jpg 640w,
lighthouse-1280.jpg 1280w">
瀏覽器會(huì)根據(jù)對(duì)應(yīng)的瀏覽器視圖寬度來(lái)選擇展示圖片

上邊這個(gè)例子,左邊的視圖差不多800px寬,瀏覽器就會(huì)加載-640.jpg那副圖,除非設(shè)備分辨率是2x類(lèi)型——這樣的花就需要-1280.jpg了
通過(guò)加入<picture>標(biāo)簽,<img/>和<source>標(biāo)簽都可以使用sizes屬性了。
<picture>
<source media="(min-width: 800px)"
sizes="80vw"
srcset="lighthouse-landscape-640.jpg 640w,
lighthouse-landscape-1280.jpg 1280w,
lighthouse-landscape-2560.jpg 2560w">
<img src="lighthouse-160.jpg" alt="lighthouse"
sizes="80vw"
srcset="lighthouse-160.jpg 160w,
lighthouse-320.jpg 320w,
lighthouse-640.jpg 640w,
lighthouse-1280.jpg 1280w">
</picture>
上邊的這個(gè)例子里如果瀏覽器的寬度超過(guò)了800px,就會(huì)顯示這個(gè)帶有陸地的大圖。

加載其他的圖片格式
<source>標(biāo)簽的type屬性可以用來(lái)加載其他格式的圖片,但這個(gè)屬性并不是全部都合適的,比如WebP格式在支持的瀏覽器上加載出來(lái)就是WebP,而在不支持他的瀏覽器上加載出來(lái)就是JPEG.
<picture>
<source type="image/webp" srcset="images/butterfly.webp">
<img src="images/butterfly.jpg" alt="a butterfly">
</picture>
譯者注:
[1] WebP:這是谷歌定義的一種新的文件格式,目前還未得到大范圍推廣,chrome和opera支持,與之一起的還有webM,互聯(lián)網(wǎng)專(zhuān)用的視頻格式
[2] sizes="(max-width: 30em) 100vw 這里的VW單位意思是“viewport width”,前面的數(shù)字代表的是一個(gè)百分比,100vw的意思是“對(duì)象寬度占視圖寬度的100%”,是一個(gè)寬度單位。
[3] calc()方法.calc 是 calculate 計(jì)算的簡(jiǎn)寫(xiě),這個(gè)方法允許以表達(dá)式的方式來(lái)定義樣式,比如calc(100% - 30px)意思就是寬度是比100%視圖寬度窄30px。MDN提示這是一個(gè)實(shí)驗(yàn)性質(zhì)的方法。