一.问题背景
这个需求有点奇怪,移动支持的最佳方案是专门建一个移动站,服务端做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像素宽度都在320px
到480px
之间,当然,使用这些查询规则的前提是设置viewport meta:
<meta name="viewport" content="width=device-width"/>
把布局视口的宽度设置为CSS像素宽度,所以不用担心超高分辨率的战斗机,至于Retina屏幕,压根和我们的目标(区分移动设备)没关系。关于三种视口和Retina屏幕的详细解释,请查看完全理解px,dpr,dpi,dip
P.S.Moto 360 Watch的CSS像素宽度为218px
到281px
,总之,手表不会超过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,稳赚不赔