只针对移动设备的媒体查询

一.问题背景

这个需求有点奇怪,移动支持的最佳方案是专门建一个移动站,服务端做UA检测,返回对应的内容

P.S.关于移动适配方案的更多信息,请查看CSS进阶篇 二.如何支持移动浏览器

场景:PC站已经建好,且不打算改变HTML结构,mobile first原则不适用

P.S.其实场景是CSS规范翻译完毕,估计自己以后用手机看得多,所以想通过媒体查询适配手机显示。只针对移动设备调整布局,媒体查询匹配目标是移动设备(这里特指手机,且不管横屏竖屏)

二.可选方案

1.breakpoints

最常见的方式,通过屏幕宽度(用CSS像素描述的宽度)来区分各种设备,如下:

@media (min-width:320px) { /* smartphones, portrait iPhone, portrait 480x320 phones (Android) */ }
@media (min-width:480px) { /* smartphones, Android phones, landscape iPhone */ }
@media (min-width:600px) { /* portrait tablets, portrait iPad, e-readers (Nook/Kindle), landscape 800x480 phones (Android) */ }
@media (min-width:801px) { /* tablet, landscape iPad, lo-res laptops ands desktops */ }
@media (min-width:1025px) { /* big landscape tablets, laptops, and desktops */ }
@media (min-width:1281px) { /* hi-res laptops and desktops */ }

/* 另外 */
min-width: 480px: Will target mobile devices in landscape mode and up

以上内容来自stackwoverflow 2011年的答案

强调2011年是为了引发思考:当年的手机屏幕分辨率小,也没有Retina屏幕这种东西。那么,现在这样的媒体查询规则还有效吗?

换句话说,为什么max-width: 480px能匹配1080x1920px的大屏手机?

关键在于这两个px不是同一个东西,前者是CSS像素,后者是物理像素。而包括iPhone6p以及巨屏三星在内的所有手机,CSS像素宽度都在320px480px之间,当然,使用这些查询规则的前提是设置viewport meta:

<meta name="viewport" content="width=device-width"/>

把布局视口的宽度设置为CSS像素宽度,所以不用担心超高分辨率的战斗机,至于Retina屏幕,压根和我们的目标(区分移动设备)没关系。关于三种视口和Retina屏幕的详细解释,请查看完全理解px,dpr,dpi,dip

P.S.Moto 360 Watch的CSS像素宽度为218px281px,总之,手表不会超过320px,他们不会故意制造混乱

2.touch事件

一种取巧的方法,如下:

<script type="text/javascript"> 
    //detect if browser supports touch
    var is_touch_device = 'ontouchstart' in document.documentElement;
    if(is_touch_device){
        $('body').addClass('touchDevice');
    }else{
        $('body').addClass('notTouch');
    };
</script>

假设移动设备 === 支持touch事件,可能会存在兼容性问题,但不会很严重(比如IE不要也罢)

3.设备特性

根据屏幕的宽度以及DPR区分各个设备,比如iPhone6:

/* Portrait and Landscape */
@media only screen 
  and (min-device-width: 375px) 
  and (max-device-width: 667px) 
  and (-webkit-min-device-pixel-ratio: 2) { 

}
/* Portrait */
@media only screen 
  and (min-device-width: 375px) 
  and (max-device-width: 667px) 
  and (-webkit-min-device-pixel-ratio: 2)
  and (orientation: portrait) { 

}

更多设备对应的查询规则请查看Media Queries for Standard Devices

P.S.虽然这个方案并不能很好的解决我们的问题,但可以用来锦上添花(针对特定设备做处理,比如给Retina屏幕开小灶)

三.结论

采用了方案1 breakpoints,具体如下:

/* Smartphones (portrait and landscape) ----------- */
@media only screen
and (min-device-width : 320px)
and (max-device-width : 480px) {
/* Styles */
}

以上代码来自CSS Media Queries For Mobile Devices

其实,单从结论上看,我们根本不需要寻找其它方案,这种最简单的方法就是最有效的

但原理牵扯的东西比较多:三个视口,DPR,DPI,CSS像素,物理像素等等

不明所以的人一定会对高分辨率战斗机和Retina屏幕心存疑虑,引别人的回答

What makes you think media queries won’t work?

Apparently, Galaxy S4’s CSS pixel ratio is 3.0, therefore, while its physical resolution is 1080×1920, its CSS resolution is still 360×640 – similar to Galaxy S3.

There are also media queries that test for pixel density. They may help you to serve high-res pictures or vector graphics to hi-dpi devices.

http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density#Samsung

http://bjango.com/articles/min-device-pixel-ratio/

Plus, take a look at this article:

http://www.html5rocks.com/en/mobile/high-dpi/

Awesome database of screen specifications

http://screensiz.es/phone

P.S.英文看着更容易让人信服,对吧,为什么呢?

四.注意事项

对CSS规范使用媒体查询时发现:

微信内置浏览器不支持
@media (min-device-width : 320px)
需要修改html meta
width=device-width再用
@media (min-width:480px)

很隐晦的问题,所以千万不要使用min-device-width,看似省事

参考资料

都链接在上文里了,另外,强烈建议看看完全理解px,dpr,dpi,dip,稳赚不赔

发表评论

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

*

code