响应式设计的思考:媒体查询-Web前端之家

响应式布局,已经慢慢开始普遍了,但是响应式页面的性能问题就接踵而来了。今天就“响应式页面图片处理”来分析下,如何使得我们的响应式页面在PC和移动端快速的加载图片和修饰背景图,我们直接来点干货,从一些案例下手:

网页制作web前端之家文章简介:媒体查询与http请求

测试一:img标签

Jason Grigsby发表了篇文章,《CSS Media Query for Mobile is Fool’s
Gold》对媒体查询吐槽,大意是在移动设备上使用媒体查询会造成很多资源的浪费——浏览器请求到很多用不到的图片等资源,然后写了一些测试用例测试一些可用方法。然后Tim
Kadlec写了篇《Media Query & Asset Downloading
Results》,用js自动化的测试了Jason Grigsby的用例。

本测试尝试通过对img标签的父级元素使用display:none来隐藏图片。HTML和CSS代码如下:

本文主要整理自Tim的这篇文章。我们来看看到底会不会浪费资源,并寻找下最优的方案。

@mediaalland{#test1{display:none;}}

测试一:img标签

测试结果

本测试尝试通过对img标签的父级元素使用display:none来隐藏图片。HTML和CSS代码如下:

如果有一种应该100%避免的隐藏图片的方法,那就是display:none。它基本上是没有用的。貌似Opera
Mobile和Opera
mini不会下载图片,而其它浏览器都会下载。Opera可以比较好的控制资源的下载,对于用户看不到的内容,它不会预先下载。

123

123

@media all and  {#test1 { display:none; }}

浏览器

测试结果

请求图片

如果有一种应该100%避免的隐藏图片的方法,那就是display:none。它基本上是没有用的。貌似Opera
Mobile和Opera
mini不会下载图片,而其它浏览器都会下载。Opera可以比较好的控制资源的下载,对于用户看不到的内容,它不会预先下载。

Android 2.1+请求Blackberry +请求Chrome Mobile请求Fennec 请求Firefox
请求IE请求iOS 请求Opera 请求Opera Mini 不请求Opera Mobile
不请求RockMelt请求Safari 请求结论测试二:背景图片display:none

浏览器

在本例中,div被设置了background-image。如果屏幕宽度小于600px,div就被设置为display:none。HTML和CSS代码如下:

请求图片

#test2{background-image:url('images/test2.png');width:200px;height:75px;}@mediaalland{#test2{display:none;}}

Android 2.1+ 请求 Blackberry + 请求 Chrome Mobile 请求 Fennec 请求
Firefox 请求 IE 请求 iOS 请求 Kindle 请求 Opera Mini 不请求 Opera Mobile
不请求 RockMelt 请求 Safari 请求 结论测试二:背景图片display:none

测试结果

在本例中,div被设置了background-image。如果屏幕宽度小于600px,div就被设置为display:none。HTML和CSS代码如下:

结果和测试一一样:除了Opera mini和Opera
Mobile和Firefox,所有浏览器都会下载图片。

1

12345678

#test2 {background-image:url;width:200px;height:75px;}@media all and  {#test2 {display:none;}}

浏览器

测试结果

请求图片

结果和测试一一样:除了Opera mini和Opera
Mobile和Firefox,所有浏览器都会下载图片。

Android 2.1+请求Blackberry +请求Chrome Mobile请求Fennec 请求Firefox
不请求IE请求iOS 请求Opera 请求Opera Mini 不请求Opera Mobile
不请求RockMelt请求Safari 请求Silk请求结论

浏览器

同样:不要这样做。不过,像后面其它的测试,有其它的方法可以隐藏背景图片同时避免多余请求。

请求图片

测试三:背景图片的父级元素被设置为display:none

Android 2.1+ 请求 Blackberry + 请求 Chrome Mobile 请求 Fennec 请求
Firefox 不请求 IE 请求 iOS 请求 Kindle 请求 Opera Mini 不请求 Opera
Mobile 不请求 RockMelt 请求 Safari 请求 Silk 请求 结论

本测试中,对一个div标签设置背景图片,然后对其父元素在浏览器宽度小于600px时设置display:none。HTML和CSS代码如下:

同样:不要这样做。不过,像后面其它的测试,有其它的方法可以隐藏背景图片同时避免多余请求。

#test3div{background-image:url('images/test3.png');width:200px;height:75px;}@mediaalland{#test3{display:none;}}

测试三:背景图片的父级元素被设置为display:none

测试结果

本测试中,对一个div标签设置背景图片,然后对其父元素在浏览器宽度小于600px时设置display:none。HTML和CSS代码如下:

表面上,这个测试貌似和测试二没太明显的区别,但是结论是这个方法是比较靠谱的。。。

123

12345678910

#test3 div {background-image:url;width:200px;height:75px;}@media all and  {#test3 {display:none;}}

浏览器

测试结果

请求图片

表面上,这个测试貌似和测试二没太明显的区别,但是结论是这个方法是比较靠谱的。。。

Android 2.1+不请求Blackberry 不请求Chrome Mobile不请求Fennec 请求Firefox
不请求IE 9+不请求iOS 不请求Opera 不请求Opera Mini 不请求Opera Mobile
不请求结论

浏览器

这个方法不错。除了不太成熟的Fennec,其它浏览器都不请求不必要显示的图片。

请求图片

测试四:背景图片层叠

Android 2.1+ 不请求 Blackberry 不请求 Chrome 不请求 Chrome Mobile 不请求
Fennec 请求 Firefox 不请求 IE 9+ 不请求 iOS 不请求 Kindle 不请求 Opera
不请求 Opera Mini 不请求 Opera Mobile 不请求 结论

本测试中,一个div被设置了背景图片。如果浏览器宽度小于600px,该div会被给到另一个背景图片。该测试用来检测是否两个图片都会被请求,还是只请求需要的。HTML和CSS代码如下:

这个方法不错。除了不太成熟的Fennec,其它浏览器都不请求不必要显示的图片。

#test4{background-image:url('images/test4-desktop.png');width:200px;height:75px;}@mediaalland{#test4{background-image:url('images/test4-mobile.png');}}

测试四:背景图片层叠

测试结果

本测试中,一个div被设置了背景图片。如果浏览器宽度小于600px,该div会被给到另一个背景图片。该测试用来检测是否两个图片都会被请求,还是只请求需要的。HTML和CSS代码如下:

比设置display:none好一些,这种方法的结果有点儿乱:

1

12345678910

#test4 {background-image:url('images/test4-desktop.png');width:200px;height:75px;}@media all and  {#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 不请求Chrome Mobile不请求Fennec 请求Firefox 不请求IE
9+不请求iOS 请求Opera 不请求Opera Mini 不请求Opera Mobile 不请求Safari
4.0请求Safari 5.0+不请求结论

浏览器

我会避免使用这种方法。尽管环境在改善,但是在Android市场中占主导地位的Android
2.x版本依然会像Fennec和Kindle一样同时下载两个图片。三者中,尤其因为Android,我会推荐寻找别的方案。

同时请求

测试五:大背景图片被设置min-width

Android 2.1-3.0? 请求 Android 4.0 不请求 Blackberry 6.0 请求 Blackberry
7.0 不请求 Chrome 不请求 Chrome Mobile 不请求 Fennec 请求 Firefox 不请求
IE 9+ 不请求 iOS 不请求 Kindle 不请求 Opera Mini 不请求 Opera Mobile
不请求 Safari 4.0 请求 Safari 5.0+ 不请求 结论

本测试中,一个div元素在浏览器宽度大于601px时被设置一个背景图片,然后在浏览器宽度小于600px时被设置为另一个背景图片。HTML和CSS代码如下:

我会避免使用这种方法。尽管环境在改善,但是在Android市场中占主导地位的Android
2.x版本依然会像Fennec和Kindle一样同时下载两个图片。三者中,尤其因为Android,我会推荐寻找别的方案。

@mediaalland{#test5{background-image:url('images/test5-desktop.png');width:200px;height:75px;}}@mediaalland{#test5{background-image:url('images/test5-mobile.png');width:200px;height:75px;}}

测试五:大背景图片被设置min-width

塞班岛贵宾会,测试结果

本测试中,一个div元素在浏览器宽度大于601px时被设置一个背景图片,然后在浏览器宽度小于600px时被设置为另一个背景图片。HTML和CSS代码如下:

浏览器

1

1234567891011121314

@media all and  {#test5 {background-image:url('images/test5-desktop.png');width:200px;height:75px;}}@media all and  {#test5 {background-image:url('images/test5-mobile.png');width:200px;height:75px;}}

同时请求

测试结果

Android 2.1+不请求Blackberry 不请求Chrome Mobile不请求Fennec 请求Firefox
不请求IE 9+不请求iOS 不请求Opera 不请求Opera Mini 不请求Opera Mobile
不请求结论

浏览器

这次更多的浏览器一起玩了。但是,Fennec一如既往得不能自已。Android
2.x比较怪异。它会同时请求两个图片——但只有在屏幕宽度大于600px匹配到min-width时才这样。这种行为貌似在Android
3.0版本中被改进了。这是件诡异的事情,我很好奇它为什么会这样。其 实,有个好消息。Jason Grigsby
说他的对本例的测试结果和我的不太一样。所以我又在一些Android
2.x机器上跑了一下这个测试。结论是,我最初的测试结果不太正确,Android
2.x表现很好,我最初测试的那个平台有问题。这不仅仅对于开发者来说是个好消息,对我本人来说更是恢复了对人类的信心。。。。。。。

同时请求

但是这依然不够,你将需要对IE8以下浏览器提供替代方案,那些版本的浏览器不支持media
query,所以没有图片会被显示。当然,这个问题可以用条件注释来简单的兼容一下。

Android 2.1+ 不请求 Blackberry 不请求 Chrome 不请求 Chrome Mobile 不请求
Fennec 请求 Firefox 不请求 IE 9+ 不请求 iOS 不请求 Kindle 不请求 Opera
不请求 Opera Mini 不请求 Opera Mobile 不请求 结论

测试六:背景图片display:none

这次更多的浏览器一起玩了。但是,Fennec一如既往得不能自已。Android
2.x比较怪异。它会同时请求两个图片——但只有在屏幕宽度大于600px匹配到min-width时才这样。这种行为貌似在Android
3.0版本中被改进了。这是件诡异的事情,我很好奇它为什么会这样。
其实,有个好消息。Jason Grigsby
说他的对本例的测试结果和我的不太一样。所以我又在一些Android
2.x机器上跑了一下这个测试。结论是,我最初的测试结果不太正确,Android
2.x表现很好,我最初测试的那个平台有问题。这不仅仅对于开发者来说是个好消息,对我本人来说更是恢复了对人类的信心。。。。。。。

本测试和测试二类似,但是使用了max-device-width来替代max-width。HTML和CSS代码如下:

但是这依然不够,你将需要对IE8以下浏览器提供替代方案,那些版本的浏览器不支持media
query,所以没有图片会被显示。当然,这个问题可以用条件注释来简单的兼容一下。

#test6{background-image:url('images/test6.png');width:200px;height:75px;}@mediaalland(max-device-width:600px){#test6{display:none;}}

测试六:背景图片display:none

结论

本测试和测试二类似,但是使用了max-device-width来替代max-width。HTML和CSS代码如下:

好吧,不用浪费时间了,这个测试结果和测试二的基本一致。

1

12345678910

#test6 {background-image:url;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代码如下:

最后一个测试,是为了new
ipad提供的,它使用了retina屏幕,这样它就要使用更高分辨率的图片了。

#test7{background-image:url('images/test7-lowres.png');width:200px;height:75px;}@mediaonlyscreenand(-webkit-min-device-pixel-ratio:1.5),onlyscreenand(-moz-min-device-pixel-ratio:1.5),onlyscreenand(-o-min-device-pixel-ratio:3/2),onlyscreenand(min-device-pixel-ratio:1.5){#test7{background-image:url('images/test7-highres.png');width:200px;height:75px;}}

本例中,一个div被给到一个背景图片。然后,通过使用min-device-pixel-ratio属性,如果比例大于1.5,一个新的背景图片将会被用到。

测试结果

HTML和CSS代码如下:

浏览器

1

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 不请求Chrome Mobile不请求Fennec 不请求Firefox 不请求IE
9+不请求iOS 不请求Opera 不请求Opera Mini 不请求Opera Mobile 不请求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或者更高,这样会比较安全一点儿。。。

Android 2.1-3.0? 请求 Android 4.0 不请求 Blackberry 6.0 不请求
Blackberry 7.0 不请求 Chrome 不请求 Chrome Mobile 不请求 Fennec 不请求
Firefox 不请求 IE 9+ 不请求 iOS 不请求 Kindle 不请求 Opera 不请求 Opera
Mini 不请求 Opera Mobile 不请求 Safari 4.0+ 不请求 结论

推荐

为了安全,这个方案可以多测试一些。看起来这种方法在绝大多数情况下是可用的。但是不幸的是,貌似Android
2.x会同时下载两个图片如果设备像素比大于或等于1.5时(或者你在media
query中设置的别的任何值)
。所以,在本例中,如果你使用了一个高分辨率的Android
2.x的设备,会比较苦逼。。。

如果你要隐藏一张内容图片,display:none是无效的,所以我推荐使用javascript方案或者服务器端实现;

好消息是,到目前位置,我还没听说有那一款Android
2.x的设备的屏幕比例超过1.5.所以如果你的项目面向使用retina屏幕的ios设备,你可以将min-device-pixel-ratio设置到2或者更高,这样会比较安全一点儿。。。

如果你要隐藏一张背景图片,最好的方法是隐藏其父级元素。如果你不方便这样做,那就用一个层叠样式覆盖掉它吧,然后将设置background-image:none;

推荐
如果你要隐藏一张内容图片,display:none是无效的,所以我推荐使用javascript方案或者服务器端实现;
如果你要隐藏一张背景图片,最好的方法是隐藏其父级元素。如果你不方便这样做,那就用一个层叠样式覆盖掉它吧,然后将设置background-image:none;
如果你要切换多张图片,就把他们全部用media query定义吧。
关于响应式设计的思考

如果你要切换多张图片,就把他们全部用media query定义吧。

媒体查询现在最大的用处就是响应式设计了,神飞翻译这篇文章也是因为最近在思考响应式设计的效率问题。通过这些测试结果,我们在实现响应式设计的网站时,最好先处理移动设备,然后再向高分辨率设备升级。然后使用图片等外部资源的选择器,一定要写到媒体查询中去。

关于响应式设计的思考

反馈

媒体查询现在最大的用处就是响应式设计了,神飞翻译这篇文章也是因为最近在思考响应式设计的效率问题。通过这些测试结果,我们在实现响应式设计的网站时,最好先处理移动设备,然后再向高分辨率设备升级。然后使用图片等外部资源的选择器,一定要写到媒体查询中去。

如果你觉得这些测试结果有任何错误的地方,欢迎在评论中提出,然后这些测试用例Tim都在GitHub上开源了,感兴趣的话可以fork下。。。

发表评论

电子邮件地址不会被公开。 必填项已用*标注