09 August 2014
关于移动端自适应页面的一些总结
移动端项目,由于手机屏幕大小不一,基本都需要实现自适应(貌似现在网上流行叫适配)。
目前个人使用的移动端自适应基本上有这么几种办法:
- 所有定位用百分比
%
; - 所有单位
em
; - 所有单位
rem
;
将自己最近几个项目踩的坑一个一个列一列,做个总结。
以下的内容都是针对移动端,并未考虑PC端
1. 百分比定位
百分比定位,既整个页面,都使用百分比作为单位,包括margin
,padding
,width
,height
,top
,left
等。
这有例子:点击查看百分比布局例子 (由于是移动端项目,推荐使用手机模拟器查看)
如果想要熟练进行百分比布局,首先就要清楚他们各自的百分比是相对于谁来计算的。
首先:margin
,padding
,width
,left
,right
这几项的百分比,全部都是按照其父元素宽度的百分比进行计算的。(天坑:安卓2.3中,margin-top是按照高度计算百分比的,后面细说)
然后就是,height
,top
,bottom
的百分比是按照父元素的高度计算的。
发现没有,height
是按照父元素的高度计算的,那该如何实现宽度自适应呢?
在元素宽高比已知的情况下,可以通过设置 padding-top
的百分比为高宽的百分比例,即可将元素按一定比例进行宽度自适应了。
但这样做有个劣势就是如果这个元素内部还有别的元素,需要将内部元素的父元素设置为 position:absolute
,否则内部元素将被padding顶下来。
然后就是布局,全部用 margin
定位。(当然了,如果你某些元素需要高度自适应,需要使用 height
百分比与 top
百分比,自己抉择)
如果有人比较追(qiang)求(po)完(zheng)美(比如我这个强迫症),想让字体大小也自适应缩放,一开始我是这样做的。
设置字体的单位为 em
( or rem
,后细说),然后绑定 window.onresize
,得到屏幕宽度与你的UE图大小的原始宽度的比例,并将 body
上的 font-size
设置等比乘上这个比例即可。
好了,说说上面提到的那个天坑。
测试安卓2.3的时候,我发现了一个很蛋疼的事情,某些安卓2.3中,默认浏览器中的 margin-top
是按照高度 height
的百分比计算的,这样的话,我想实现宽度自适应的垂直位置定位, margin-top
与 top
属性都是基于高度计算百分比的,无解。
最后我是按照前面设置 font-size
的那个办法,window.onresize
时判断屏幕宽度来设置 top
的比例。两个字—蛋疼。
于是乎,我开始研究新的自适应布局方式,然后某一天我惊讶的发现, em
与 rem
单位,完美被移动端设备支持!!!
2. em布局
em布局,前面提到过 em
单位,如果不清楚em单位的定义可以google or 问度娘,这里不做概念性介绍,只记录用法。
所有距离单位都可以使用 em
作为单位,我发现有些同学以为只有字体可以设置 em
(虽然这货本身就是一个描述字体的单位..),其实所有属性的单位都可以使用 em
的, em
是什么呢? font-size
属性上的 em
,是相对其父元素的字体大小的比值。如果等于其父元素字体大小,既 1em
。
px
与 em
的关系为:
如果父元素字体为 16px
,那么 1px = 16em
。方便的做法是在 body
上设置 font-size:62.5%
,然后 1em=10px
,或者使用公式 1em =1*1px/16
来设置 em
的值。
其实如果存在子元素与父元素字体大小不一样的情况,都还好,还能忍。。
不能忍的是,一个元素的 width
, height
, padding
, margin
, top
, left
等属性的 em
值,是按照元素自己的字体大小计算的!这样的话,如果你的父元素上设置了字体大小,你按比例计算完自己的字体大小后,还得计算每一个 width
…等属性的 em
值!四个字–灰常蛋疼!
好了,不能忍,跟原工作室老大吐槽,这个时候他提醒我, rem
啊,caniuse一查,我擦咧,安卓2.3+全部支持,好了,刚拿到手的 em
马上丢掉,转投 rem
。
Ok,重头戏来了!
3. rem布局
rem
是什么?它其实跟 em
灰常接近,只是相对的元素不一样了。
em
是相对父元素,而 rem
指的是相对 root element
。什么是root element?就是一个页面DOM tree的根节点,html
标签。
那么所有单位都使用 rem
的效果是什么呢?
当我们所有单位都设置成 rem
后,整个页面的大小比例都基于一个值,root element
的字体大小!
随便你想怎么适应,只要元素内部宽高比例不变,改变一个字体大小就可以了!
当将html上的font-size从1%~100%变,你可以很爽的看到整个页面像被矢量放大一样变大,试试吧,感觉良好!
有怎么改变字体大小呢?其实前面已经提到过了,想怎么变, window.onresize
时设置比例就哦可了。
具体做法可以参考这里。
总结
其实并没有说哪一种布局好,最好的做法其实是把这三种结合起来使用的,只要你清楚明白他们具体的用法,每一种都用的炉火纯青,具体哪些元素用哪个单位,信手拈来,武林高手都是不拘于条条框框的,将他们都理解透,结合起来,这样才是最高境界。
(写的乱七八糟。。欢迎讨论交流拍砖)
2014.11.4日补充
关于计算屏幕宽度并设置html上的rem值的js代码,最开始我是用的自己的粗糙版本,后来代码由介右同学加工优化后,我参考了winter的手机淘宝的解决方案,并结合了自己的使用场景,整理了一版放在了这里。
该方案自去年我在组里推广后,已从去年开始投入到生产环境。
2015.5.10日补充
其实光用rem
实现了宽度自适应还是没用,当一些需要布满全屏的页面,光宽度自适应了,你还需要面对各种各样高度的情景。
当然media-query
是最好使的,但是你不能直接写死高度,我试过,写了5、6套,还是不够用。
由于rem
布局的页面整个页面大小已经是相对宽度的了, 其实要实现真正覆盖所有case, 必须高度也使用百分比来写media-query
。
折腾后发现一个神器 – media-query
中的aspect-ratio
宽高比!
通过rem
布局以及aspect-ratio
可以简单粗暴的解决一切分辨率下的移动端页面适配问题,简直是太暴力了!
总结的文章还没写, 有兴趣的同学可以自己先研究一下aspect-ratio
,文章出来以后我将及时更新。Thx!
Posted in 2014-08-09 17:20