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標簽的父級元素使用display:none來隱藏圖片。Html和CSS代碼如下:
1 2 3
<div id="test1"> <img src="images/test1.png" alt="" /> </div>
1 2 3
@media all and (max-width: 600px) { #test1 { display:none; } }
如果有一種應該100%避免的隱藏圖片的方法,那就是display:none。它基本上是沒有用的。貌似Opera Mobile和Opera mini不會下載圖片,而其它浏覽器都會下載。Opera可以比較好的控制資源的下載,對於用戶看不到的內容,它不會預先下載。
很簡單:不要這樣用。
運行測試
在本例中,div被設置了background-image。如果屏幕寬度小於600px,div就被設置為display:none。Html和CSS代碼如下:
1
<div id="test2"></div>
1 2 3 4 5 6 7 8
#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,所有浏覽器都會下載圖片。
同樣:不要這樣做。不過,像後面其它的測試,有其它的方法可以隱藏背景圖片同時避免多余請求。
運行測試
本測試中,對一個div標簽設置背景圖片,然後對其父元素(也是個div)在浏覽器寬度小於600px時設置display:none。Html和CSS代碼如下:
1 2 3
<div id="test3"> <div></div> </div>
1 2 3 4 5 6 7 8 9 10
#test3 div { background-image:url('images/test3.png'); width:200px; height:75px; } @media all and (max-width: 600px) { #test3 { display:none; } }
表面上,這個測試貌似和測試二沒太明顯的區別,但是結論是這個方法是比較靠譜的。。。
這個方法不錯。除了不太成熟的Fennec,其它浏覽器都不請求不必要顯示的圖片。
運行測試
本測試中,一個div被設置了背景圖片。如果浏覽器寬度小於600px,該div會被給到另一個背景圖片。該測試用來檢測是否兩個圖片都會被請求,還是只請求需要的。Html和CSS代碼如下:
1
<div id="test4"></div>
1 2 3 4 5 6 7 8 9 10
#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市場中占主導地位的Android 2.x版本依然會像Fennec和Kindle一樣同時下載兩個圖片。三者中,尤其因為android(的碎片化),我會推薦尋找別的方案。
運行測試
本測試中,一個div元素在浏覽器寬度大於601px時被設置一個背景圖片,然後在浏覽器寬度小於600px時被設置為另一個背景圖片。Html和CSS代碼如下:
1
<div id="test5"></div>
1 2 3 4 5 6 7 8 9 10 11 12 13 14
@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; } }
這種方案好一點兒:
這次更多的浏覽器一起玩了。但是,Fennec一如既往得不能自已。Android 2.x比較怪異。它會同時請求兩個圖片——但只有在屏幕寬度大於600px匹配到min-width時才這樣。這種行為貌似在android 3.0版本中被改進了。這是件詭異的事情,我很好奇它為什麼會這樣。 其實,有個好消息。Jason Grigsby 說他的對本例的測試結果和我的不太一樣。所以我又在一些Android 2.x機器上跑了一下這個測試。結論是,我最初的測試結果不太正確,android 2.x表現很好,我最初測試的那個平台有問題。這不僅僅對於開發者來說是個好消息,對我本人來說更是恢復了對人類的信心。。。。。。。
但是這依然不夠,你將需要對IE8以下浏覽器提供替代方案,那些版本的浏覽器不支持media query,所以沒有圖片會被顯示。當然,這個問題可以用條件注釋來簡單的兼容一下。
運行測試
本測試和測試二類似,但是使用了max-device-width來替代max-width。Html和CSS代碼如下:
1
<div id="test6"></div>
1 2 3 4 5 6 7 8 9 10
#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代碼如下:
1
<div id="test7"></div>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#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.x會同時下載兩個圖片如果設備像素比大於或等於1.5時(或者你在media query中設置的別的任何值)。所以,在本例中,如果你使用了一個高分辨率的android 2.x的設備,會比較苦逼。。。
好消息是,到目前位置,我還沒聽說有那一款android 2.x的設備的屏幕比例超過1.5.所以如果你的項目面向使用retina屏幕的iOS設備,你可以將min-device-pixel-ratio設置到2或者更高,這樣會比較安全一點兒。。。