Jason Grigsby發表了篇文章,《CSS Media Query for Mobile is Fool’s Gold》對媒體查詢(media query)吐槽,大意是在行動裝置上使用媒體查詢會造成很多資源的浪費——瀏覽器請求到很多用不到的圖片等資源,然後寫了一些測試案例測試一些可用方法。然後Tim Kadlec寫了篇《Media Query & Asset Downloading Results》,用js自動化的測試了Jason Grigsby的用例。
本文主要整理自Tim的這篇文章。我們來看看到底會不會浪費資源,並尋找下最優的方案。
直接看結果吧~~
測試一:img標籤
運行測試
本測試嘗試通過對img標籤的父級元素使用display:none來隱藏圖片。HTML和CSS代碼如下:
123 |
<div id="test1"><img src="images/test1.png" alt="" /></div> |
123 |
@media all and (max-width: 600px) {#test1 { display:none; }} |
測試結果
如果有一種應該100%避免的隱藏圖片的方法,那就是display:none。它基本上是沒有用的。貌似Opera Mobile和Opera mini不會下載圖片,而其它瀏覽器都會下載。Opera可以比較好的控制資源的下載,對於使用者看不到的內容,它不會預先下載。
瀏覽器 |
請求圖片 |
Android 2.1+ |
請求 |
Blackberry (6.0+) |
請求 |
Chrome (4.1)+ |
請求 |
Chrome Mobile |
請求 |
Fennec (10.0+) |
請求 |
Firefox (3.6+) |
請求 |
IE |
請求 |
iOS (4.26+) |
請求 |
Kindle (3.0) |
請求 |
Opera (11.6+) |
請求 |
Opera Mini (6.5+) |
不請求 |
Opera Mobile (11.5) |
不請求 |
RockMelt |
請求 |
Safari (4+) |
請求 |
結論
很簡單:不要這樣用。
測試二:背景圖片display:none
運行測試
在本例中,div被設定了background-image。如果螢幕寬度小於600px,div就被設定為display:none。HTML和CSS代碼如下:
12345678 |
#test2 {background-image:url('images/test2.png');width:200px;height:75px;}@media all and (max-width: 600px) {#test2 {display:none;}} |
測試結果
結果和測試一一樣:除了Opera mini和Opera Mobile和Firefox,所有瀏覽器都會下載圖片。
瀏覽器 |
請求圖片 |
Android 2.1+ |
請求 |
Blackberry (6.0+) |
請求 |
Chrome (4.1)+ |
請求 |
Chrome Mobile |
請求 |
Fennec (10.0+) |
請求 |
Firefox (3.6+) |
不請求 |
IE |
請求 |
iOS (4.26+) |
請求 |
Kindle (3.0) |
請求 |
Opera (11.6+) |
請求 |
Opera Mini (6.5+) |
不請求 |
Opera Mobile (11.5) |
不請求 |
RockMelt |
請求 |
Safari (4+) |
請求 |
Silk |
請求 |
結論
同樣:不要這樣做。不過,像後面其它的測試,有其它的方法可以隱藏背景圖片同時避免多餘請求。
測試三:背景圖片的父級元素被設定為display:none
運行測試
本測試中,對一個div標籤設定背景圖片,然後對其父元素(也是個div)在瀏覽器寬度小於600px時設定display:none。HTML和CSS代碼如下:
123 |
<div id="test3"><div></div></div> |
12345678910 |
#test3 div {background-image:url('images/test3.png');width:200px;height:75px;}@media all and (max-width: 600px) {#test3 {display:none;}} |
測試結果
表面上,這個測試貌似和測試二沒太明顯的區別,但是結論是這個方法是比較靠譜的。。。
瀏覽器 |
請求圖片 |
Android 2.1+ |
不請求 |
Blackberry (6.0+) |
不請求 |
Chrome (16+) |
不請求 |
Chrome Mobile |
不請求 |
Fennec (10.0+) |
請求 |
Firefox (3.6+) |
不請求 |
IE 9+ |
不請求 |
iOS (4.26+) |
不請求 |
Kindle (3.0) |
不請求 |
Opera (11.6+) |
不請求 |
Opera Mini (6.5+) |
不請求 |
Opera Mobile (11.5) |
不請求 |
Safari (4+) |
不請求 |
結論
這個方法不錯。除了不太成熟的Fennec,其它瀏覽器都不請求不必要顯示的圖片。
測試四:背景圖片層疊
運行測試
本測試中,一個div被設定了背景圖片。如果瀏覽器寬度小於600px,該div會被給到另一個背景圖片。該測試用來檢測是否兩個圖片都會被請求,還是只請求需要的。HTML和CSS代碼如下:
12345678910 |
#test4 {background-image:url('images/test4-desktop.png');width:200px;height:75px;}@media all and (max-width: 600px) {#test4 {background-image:url('images/test4-mobile.png');}} |
測試結果
比設定display:none好一些,這種方法的結果有點兒亂:
瀏覽器 |
同時請求 |
Android 2.1-3.0? |
請求 |
Android 4.0 |
不請求 |
Blackberry 6.0 |
請求 |
Blackberry 7.0 |
不請求 |
Chrome (16+) |
不請求 |
Chrome Mobile |
不請求 |
Fennec (10.0+) |
請求 |
Firefox (3.6+) |
不請求 |
IE 9+ |
不請求 |
iOS (4.26+) |
不請求 |
Kindle (3.0) |
請求 |
Opera (11.6+) |
不請求 |
Opera Mini (6.5+) |
不請求 |
Opera Mobile (11.5) |
不請求 |
Safari 4.0 |
請求 |
Safari 5.0+ |
不請求 |
結論
我會避免使用這種方法。儘管環境在改善,但是在Android市場中佔主導地位的Android 2.x版本依然會像Fennec和Kindle一樣同時下載兩個圖片。三者中,尤其因為Android(的片段化),我會推薦尋找別的方案。
測試五:大背景圖片被設定min-width
運行測試
本測試中,一個div元素在瀏覽器寬度大於601px時被設定一個背景圖片,然後在瀏覽器寬度小於600px時被設定為另一個背景圖片。HTML和CSS代碼如下:
1234567891011121314 |
@media all and (min-width: 601px) {#test5 {background-image:url('images/test5-desktop.png');width:200px;height:75px;}}@media all and (max-width: 600px) {#test5 {background-image:url('images/test5-mobile.png');width:200px;height:75px;}} |
測試結果
這種方案好一點兒:
瀏覽器 |
同時請求 |
Android 2.1+ |
不請求 |
Blackberry (6.0+) |
不請求 |
Chrome (16+) |
不請求 |
Chrome Mobile |
不請求 |
Fennec (10.0+) |
請求 |
Firefox (3.6+) |
不請求 |
IE 9+ |
不請求 |
iOS (4.26+) |
不請求 |
Kindle (3.0) |
不請求 |
Opera (11.6+) |
不請求 |
Opera Mini (6.5+) |
不請求 |
Opera Mobile (11.5) |
不請求 |
Safari (4+) |
不請求 |
結論
這次更多的瀏覽器一起玩了。但是,Fennec一如既往得不能自已。Android 2.x比較怪異。它會同時請求兩個圖片——但只有在螢幕寬度大於600px匹配到min-width時才這樣。這種行為貌似在Android 3.0版本中被改進了。這是件詭異的事情,我很好奇它為什麼會這樣。 其實,有個好訊息。Jason Grigsby 說他的對本例的測試結果和我的不太一樣。所以我又在一些Android 2.x機器上跑了一下這個測試。結論是,我最初的測試結果不太正確,Android 2.x表現很好,我最初測試的那個平台有問題。這不僅僅對於開發人員來說是個好訊息,對我本人來說更是恢複了對人類的信心。。。。。。。
但是這依然不夠,你將需要對IE8以下瀏覽器提供替代方案,那些版本的瀏覽器不支援media query,所以沒有圖片會被顯示。當然,這個問題可以用條件注釋來簡單的相容一下。
測試六:背景圖片display:none(max-device-width)
運行測試
本測試和測試二類似,但是使用了max-device-width來替代max-width。HTML和CSS代碼如下:
12345678910 |
#test6 {background-image:url('images/test6.png');width:200px;height:75px;}@media all and (max-device-width: 600px) {#test6 {display:none;}} |
結論
好吧,不用浪費時間了,這個測試結果和測試二的基本一致。
測試七:層疊覆蓋高解析度
運行測試
最後一個測試,是為了new ipad提供的,它使用了retina螢幕,這樣它就要使用更高解析度的圖片了。
本例中,一個div被給到一個背景圖片。然後,通過使用min-device-pixel-ratio屬性,如果比例大於1.5,一個新的背景圖片將會被用到。
HTML和CSS代碼如下:
123456789101112131415 |
#test7 {background-image:url('images/test7-lowres.png');width:200px;height:75px;}@media only screen and (-webkit-min-device-pixel-ratio: 1.5),only screen and (-moz-min-device-pixel-ratio: 1.5),only screen and (-o-min-device-pixel-ratio: 3/2),only screen and (min-device-pixel-ratio: 1.5) {#test7 {background-image:url('images/test7-highres.png');width:200px;height:75px;}} |
測試結果
瀏覽器 |
同時請求 |
Android 2.1-3.0? |
請求 |
Android 4.0 |
不請求 |
Blackberry 6.0 |
不請求 |
Blackberry 7.0 |
不請求 |
Chrome (16+) |
不請求 |
Chrome Mobile |
不請求 |
Fennec (10.0+) |
不請求 |
Firefox (3.6+) |
不請求 |
IE 9+ |
不請求 |
iOS (4.26+) |
不請求 |
Kindle (3.0) |
不請求 |
Opera (11.6+) |
不請求 |
Opera Mini (6.5+) |
不請求 |
Opera Mobile (11.5) |
不請求 |
Safari 4.0+ |
不請求 |
結論
為了安全,這個方案可以多測試一些。看起來這種方法在絕大多數情況下是可用的。但是不幸的是,貌似Android 2.x會同時下載兩個圖片如果裝置像素比大於或等於1.5時(或者你在media query中設定的別的任何值)。所以,在本例中,如果你使用了一個高解析度的Android 2.x的裝置,會比較苦逼。。。
好訊息是,到目前位置,我還沒聽說有那一款Android 2.x的裝置的螢幕比例超過1.5.所以如果你的項目面向使用retina螢幕的ios裝置,你可以將min-device-pixel-ratio設定到2或者更高,這樣會比較安全一點兒。。。
推薦
- 如果你要隱藏一張內容圖片,display:none是無效的,所以我推薦使用javascript方案或者伺服器端實現;
- 如果你要隱藏一張背景圖片,最好的方法是隱藏其父級元素。如果你不方便這樣做,那就用一個層疊樣式覆蓋掉它吧(就像上面的第五個方案),然後將設定background-image:none;
- 如果你要切換多張圖片,就把他們全部用media query定義吧。
關於響應式設計的思考
媒體查詢現在最大的用處就是響應式設計了,神飛翻譯這篇文章也是因為最近在思考響應式設計的效率問題。通過這些測試結果,我們在實現響應式設計的網站時,最好先處理行動裝置,然後再向高解析度裝置升級。然後使用圖片等外部資源的選取器,一定要寫到媒體查詢中去。
反饋
如果你覺得這些測試結果有任何錯誤的地方,歡迎在評論中提出,然後這些測試案例Tim都在GitHub上開源了,感興趣的話可以fork下。。。