问题重述
本文讨论的适配不是指传统的@media
媒体查询
media query
用于区分移动设备和PC、Pad,需要针对这些设备写3套样式,一般是百分比宽度+小屏隐藏部分内容本文讨论的适配是希望在不改变页面布局/内容的前提下,希望页面在各个移动设备上视觉效果大致相同,例如:
我们希望在iphone6上和iphone4上效果大致相同,单纯css是不行的,需要js配合布局才能适应各种各样的移动设备,适配移动设备屏幕有很多难点:
屏幕宽高比不同
有很矮很胖的手机,也有很窄很长的手机
dpi不同
有屏幕特别小,但分辨率特别高的屏幕
高清屏幕(retina)下图片失真
有把一个像素点掰成几瓣显示的屏幕
media query
无助于解决这些问题,本文讨论的方案也只能勉强解决(麻烦,或者存在副作用)
一.scale/zoom缩放整个页面
1.scale与zoom的区别
zoom缩放,默认以左上角为中心,不能改,不存在覆盖周围元素的问题
scale缩放,默认以中心位置为中心,可以改,存在覆盖周围元素的问题(扩展出的东西不占空间)
zoom对子元素缩放,会破坏对齐
scale对子元素缩放,会破坏对齐,用于inline元素无效
zoom对父元素缩放,不会影响相对位置
scale对父元素缩放,如果设置以左上角为中心就不会影响相对位置
zoom兼容除Firefox之外的任何浏览器(IE5.5+)
scale兼容IE11+,兼容Firefox
DEMO: scale和zoom的区别
2.scale的副作用
input光标变粗
scale对整个页面缩放会导致IOS下页面里的Input和Textarea等输入框的光标变粗,超难看,安卓好像不会
解决方案:放弃scale适配,改用其他方案
z-index
scale可能对z-index的效果有影响,不确定,因为z-index, fixed, 软键盘这几个因素会相互影响,引发极难解决的其它问题
解决方案:float会让z无效,position的默认值也会让z无效,更多信息请查看div层调整zindex属性无效原因分析及解决方法
水平滚动条
宽屏下可能出现消不掉的水平滚动条,无论怎么设置overflow都无效
解决方案:不要给body设置scale,给wrapper设置。如果本来就是这样就反过来做(给body设置scale),还不行就考虑剥离其它因素,z-index, fixed, input等等都可能与这个有关
fixed布局失效
scale之后fixed布局会失效,fixed部分会跟着页面滚动,软键盘弹出也会引发这个问题
解决方案:改用absolute + js辅助定位,如果是复杂的fixed布局,比如fixed层上有input,还是放弃scale适配吧,bug会没完没了的
软键盘破坏布局
弹出软键盘后fixed布局就失效了,目前没得解
3.结论
可以放心去用scale缩放适配“简单”页面,“简单”的定义是:
没有input,textarea等输入框,保证不会弹出软键盘
没有复杂的z-index层级
没有fixed部分
如果页面不满足上面的任意一条,建议不要用scale来缩放适配,会被bug轰炸的
P.S.zoom缩放适配笔者用的不多,至于用scale还是zoom,有以下原则:
大前提:移动页面不要求支持IE的话可以用scale,否则乖乖用zoom吧,如果兼容Firefox很重要的话,还得添上hack
图片缩放用zoom和scale都行,整页缩放建议使用scale
4.案例
高德地图_绿色出行活动:scale缩放整页适配
5.框架
白树的pageResponse,1.4K超轻量
二.fontsize + em/rem相对单位
1.用em缩放
需要给html
(或者body
)设置font-size: 62.5%;
(所谓的65.5%hack,为了让1em=10px方便计算)。然后把所有长度单位统一成em
,当然,还需要配合js动态改变html
(或者body
)的font-size
DEMO: 用em缩放适配(注意:当前元素的fz值会影响top/left/right/bottom定位,所以只能再套一层控制fz,外层用来定位)
不建议使用em,因为:
难算
当前元素的fz值来自所有祖先元素
冗余标签
见上面的注意部分
不够灵活,难以维护
当前元素的fz值也会影响所有子元素
2.用rem缩放
最重要的是兼容性:[IE8-]不支持rem
必须给html
设置font-size: 10px;
(10px还是为了好算)。然后所有长度单位统一用rem
,再配合js设置html
的fz值就好了
DEMO:用rem缩放适配
建议尽量使用rem,rem不存在继承值的问题,无需关注祖先的fz值,非常灵活,唯一缺点是兼容性问题([IE8-]不支持)
3.注意事项
用em/rem要注意Chrome某些版本不支持font-size
小于12(即便设置了fz为10,实际渲染效果也是12),62.5%hack会失效,此时1em/1rem就不等于10px了,而是等于12px
在高版本的Chrome中,设置-webkit-text-size-adjust: none;
也没有用,移动端效果未知
4.案例
淘宝网移动版:单屏 + js模拟滑动(很强大的哟~)
5.用em/rem的好处
(一点题外话,和本文内容没什么关系)
有的页面只对文本用em/rem做字体单位,其它都用px,这是为什么?
因为px是绝对单位,而用户可以设置浏览器的默认字体大小,此时如果文本的单位是px,文本就不会根据用户的设置放大/缩小,而em/rem会
三.img+div宽度百分比,高度auto
这是老方法,没什么新奇的,缺点是文本不会跟着缩放,有两种解法:
把文本都切在图片里
缺点是页面加载变慢
js手动计算改变fz值缩放字体(配合em/rem)
根据屏幕宽高、dpi等值计算出特定的比例因子,给基础fz乘上来缩放字体,缺点是费劲,而且很难算出合适的比例因子(只能适配部分机型)
DEMO:不给了,看案例吧
案例
高德地图_全明星导航语音活动:字体没有做缩放处理,要求不高
京东移动版:字体没有做缩放处理,但内容以图片为主,影响不大
四.移动页面适配方案总结
首选scale/zoom方案,前提是页面简单(简单的定义见前文)
不行就考虑rem/em方案,注意兼容性(rem[IE8-])
实在不行就用img方案,要求不高的话可以不管字体,否则,你悲剧了