前几天的天气每天都让你汗颜,这几天龙王是将攒了好几天的水,一瓢一瓢的往下泼呀,借着雨景,饿着肚子写写移动端适配吧!
一些从事web开发的coder都会有过这样的经历:在PC端的时候,你为了适配各种浏览器而写很多的hack 和兼容,js得写、css得写,因为世界上有IE的存在,这着实让人很头疼,但是我一直相信一句话:存在即合理,如果前端开发而不需要处理兼容的话,那前端技术的含金量就会下降。尤其是js的处理,你会想要是移动端就好了,完全不需要处理js的兼容性问题;但是当你转到移动端的时候你会发现,恩js确实不需要怎么处理兼容,但是css页面兼容处理起来要远比pc要麻烦,因为移动端屏的碎片化使得其具有各种尺寸,再加上一下高清屏幕的出现(retina),等等,使得你的页面在适应所有屏幕上显得异常吃力,但是我也相信是问题就会有解决的办法。
前端技术中有很多的解决方案、媒体查询、rem布局、百分比等,但是从我个人的来看,还没有看出来哪一项技术的独自处理好兼容的,一般都是混合使用,比如说媒体查询和rem相结合等,使用什么技术这得看你的项目的具体需求,写了那么多的移动端页面,上网也找了很多的资料,拜读了各位大神的帖子,找到了自己觉得适配起来还不错的方案。rem和媒体查询怎么使用我这里就不介绍了,不清楚的自行恶补。
第一种是网易的前端适配解决方案
网易新闻的设计稿是竖版横向是750px的,依照苹果6的尺寸来做的。我们也知道设置html的font-size值是使用rem的前提,网易的做法是使用js来动态改变html的font-size值,它是根据什么计算的,这就跟设计稿有关了。网易的设计稿是750px的。为了计算方便,取一个100px的font-size为参照,那么body元素的宽度就可以设置为width: 7.5rem,于是html的font-size=deviceWidth / 7.5。这个deviceWidth就是viewport设置中的那个deviceWidth。
所以可以得出不同deviceWidth下的fotn-size的大小:
deviceWidth = 320,font-size = 320 / 7.5 = 42.6667px
deviceWidth = 375,font-size = 375 / 7.5 = 50px
deviceWidth = 414,font-size = 414 / 7.5 = 55.2px
deviceWidth = 500,font-size = 500 / 7.5 = 66.6667px
这个deviceWidth通过document.documentElement.clientWidth就能取到了,所以当页面的dom ready后,做的第一件事情就是:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';
这个7.5是根据设计稿的横向分辨率/100得来的。下面总结下网易的这种做法:
1、先拿设计稿竖着的横向分辨率除以100得到body元素的宽度:
如果设计稿基于iphone6,横向分辨率为750,body的width为750 / 100 = 7.5rem 如果设计稿基于iphone4/5,横向分辨率为640,body的width为640 / 100 = 6.4rem
2、布局时,设计图标注的尺寸除以100得到css中的尺寸:
比如你的设计稿中的banner部分的高度是300px,那你在css中就写 height:3 rem。 之所以取一个100作为参照,就是为了这里计算rem的方便!
3、在dom ready以后,通过以下代码设置html的font-size:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';
7.5只是举个例子,如果是640的设计稿,应该除以6.4。
4、font-size可能需要额外的媒介查询,并且font-size不能使用rem。网易的设置:
@media screen and (max-width:321px){ .m-navlist{font-size:15px} } @media screen and (min-width:321px) and (max-width:400px){ .m-navlist{font-size:16px} } @media screen and (min-width:400px){ .m-navlist{font-size:18px} }
最后还有2个情况要说明:
1、如果采用网易这种做法,meta中要如下设置:
<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">
2、当deviceWidth大于设计稿的横向分辨率时,html的font-size始终等于横向分辨率/body元素宽:
之所以这么干,是因为当deviceWidth大于640时,则物理分辨率大于1280(这就看设备的dpr值),应该去访问pc网站了。事实就是这样,你从手机访问网易,看到的是触屏版的页面,如果从pad访问,看到的就是电脑版的页面。如果你也想这么干,只要把总结中第三步的代码稍微改一下就行了:
var deviceWidth = document.documentElement.clientWidth;
if(deviceWidth > 640) deviceWidth = 640;
document.documentElement.style.fontSize = deviceWidth / 6.4 + 'px';
以上就是网易的移动端适配,亲测可用。
第二种是手机淘宝的前端适配方案
手淘和网易在处理前端相似之处是都使用的是rem的方式,不同的是手淘动态改变font-size和viewport.
介绍它的做法之前,先来了解一点关于viewport的知识,通常我们采用如下代码设置viewport:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
这样整个网页在设备内显示时的页面宽度就会等于设备逻辑像素大小,也就是device-width。这个device-width的计算公式为:
设备的物理分辨率/(devicePixelRatio * scale),在scale为1的情况下,device-width = 设备的物理分辨率/devicePixelRatio
devicePixelRatio称为设备像素比,每款设备的devicePixelRatio都是已知,并且不变的,目前高清屏,普遍都是2,不过还有更高的,比如2.5, 3 等,我魅蓝note的手机的devicePixelRatio就是3,苹果6plus也是3。淘宝触屏版布局的前提就是viewport的scale根据devicePixelRatio动态设置:
在devicePixelRatio为2的时候,scale为0.5 在devicePixelRatio为3的时候,scale为0.3333
这么做目的当然是为了保证页面的大小与设计稿保持一致了,比如设计稿如果是750的横向分辨率,那么实际页面的device-width,以iphone6来说,也等于750,这样的话设计稿上标注的尺寸只要除以某一个值就能够转换为rem了。通过js设置viewport的方法如下:
var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
淘宝布局的第二个要点,就是html元素的font-size的计算公式,font-size = deviceWidth / 10:
接下来要解决的问题是,元素的尺寸该如何计算,比如说设计稿上某一个元素的宽为150px,换算成rem应该怎么算呢?这个值等于设计稿标注尺寸/该设计稿对应的html的font-size。拿淘宝来说的,他们用的设计稿是750的,所以html的font-size就是75,如果某个元素时150px的宽,换算成rem就是150 / 75 = 2rem。总结下淘宝的这些做法:
1、动态设置viewport的scale
var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
2、动态计算html的font-size
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
3、布局的时候,各元素的css尺寸=设计稿标注尺寸/设计稿横向分辨率/10
4、font-size可能需要额外的媒介查询,并且font-size不使用rem,这一点跟网易是一样的。
最后还有一个情况要说明,跟网易一样,淘宝也设置了一个临界点,当设备竖着时横向物理分辨率大于1080时,html的font-size就不会变化了,原因也是一样的,分辨率已经可以去访问电脑版页面了。
关于这种做法的具体实现,淘宝已经给我们提供了一个开源的解决方案,具体请查看:
https://github.com/amfe/lib-flexible
比较网易与淘宝的做法
共同点:
- 都能适配所有的手机设备,对于pad,网易与淘宝都会跳转到pc页面,不再使用触屏版的页面
- 都需要动态设置html的font-size
- 布局时各元素的尺寸值都是根据设计稿标注的尺寸计算出来,由于html的font-size是动态调整的,所以能够做到不同分辨率下页面布局呈现等比变化
- 容器元素的font-size都不用rem,需要额外地对font-size做媒介查询
- 都能应用于尺寸不同的设计稿,只要按以上总结的方法去用就可以了
不同点
- 淘宝的设计稿是基于750的横向分辨率,网易的设计稿是基于640的横向分辨率,还要强调的是,虽然设计稿不同,但是最终的结果是一致的,设计稿的尺寸一个公司设计人员的工作标准,每个公司不一样而已
- 淘宝还需要动态设置viewport的scale,网易不用
最重要的区别就是:网易的做法,rem值很好计算,淘宝的做法肯定得用计算器才能用好了 。不过要是你使用了less和sass这样的css处理器,就好办多了,以淘宝跟less举例,我们可以这样编写less:
@baseFontSize: 75;//基于视觉稿横屏尺寸/100得出的基准font-size .px2rem(@name, @px){ @{name}: @px / @baseFontSize * 1rem; }
//使用实例 .container { .px2rem(height, 240); }
//less翻译结果: .container { height: 3.2rem; }
文章评论