固定一个某些宽度,使用一个模式,加上少许的媒体查询方案
使用flexbox解决方案
使用百分比加媒体查询
使用rem
淘宝最近开源的一个框架和网易的框架有同工之异。都是采用rem实现一稿解决所有设置自适应。在没出来这种方案之前,第一种做法的人数也不少。类似以下说到的拉钩网。看一下流云诸葛的文章。
以下摘自:从网易与淘宝的font-size思考前端设计稿与工作流
1. 简单问题简单解决
我觉得有些web app并一定很复杂,比如拉勾网,你看看它的页面在iphone4,iphone6,ipad下的样子就知道了:
它的页面有一个特点,就是:
顶部与底部的bar不管分辨率怎么变,它的高度和位置都不变
中间每条招聘信息不管分辨率怎么变,招聘公司的图标等信息都位于条目的左边,薪资都位于右边
这种app是一种典型的弹性布局:关键元素高宽和位置都不变,只有容器元素在做伸缩变换。对于这类app,记住一个开发原则就好:文字流式,控件弹性,图片等比缩放。以图描述:
这个规则是一套基本的适配规则,对于这种简单app来说已经足够,同时它也是后面要说的rem布局的基础。另外对于拉勾这种app可能需要额外媒介查询对布局进行调整的就是小屏幕设备。举例来说,因为现在很多设计稿是根据iphone6的尺寸来的,而iphon6设备宽的逻辑的像素是375px,而iphone4的逻辑像素是320个像素,所以如果你根据设计稿做出来的东西,在iphone4里面可能显示不下,比如说拉钩网底部那个下载框,你对比看下就知道了,这是4:
这是6:
6下面两边的间距比4多很多,说明拉勾对4肯定是做过适配的,从代码也可以证实这一点:
不过如果你拿到的是根据4的设计稿,那就没有问题,比4分辨率大的设备肯定能显示根据4的尺寸做出来的东西。
还有一点,这种情况css尺寸单位用px就好,不要用rem,避免增加复杂度。
2. 网易的做法
先来看看网易在不同分辨率下,呈现的效果:
从上面几张图可以看出,随着分辨率的增大,页面的效果会发生明显变化,主要体现在各个元素的宽高与间距。375*680的比320*680的导航栏明显要高。能够达到这种效果的根本原因就是因为网易页面里除了font-size之外的其它css尺寸都使用了rem作为单位,比如你看导航栏的高度设置代码:
可是在本文第1部分提到,使用rem布局结合在html上根据不同分辨率设置不同font-size有很多不好解决的麻烦,网易是如何解决的呢?最根本的原因在于,网易页面上html的font-size不是预先通过媒介查询在css里定义好的,而是通过JS计算出来的,所以当分辨率发生变化时,html的font-size就会变,不过这得在你调整分辨率后,刷新页面才能看得到效果。你看代码就知道为啥font-size是直接写到html的style上面的了(js设置的原因):
它是根据什么计算的,这就跟设计稿有关了,拿网易来说,它的设计稿应该是基于iphone4或者iphone5来的,所以它的设计稿竖直放时的横向分辨率为640px,为了计算方便,取一个100px的font-size为参照,那么body元素的宽度就可以设置为width: 6.4rem,于是html的font-size=deviceWidth / 6.4。这个deviceWidth就是viewport设置中的那个deviceWidth。根据这个计算规则,可得出本部分开始的四张截图中html的font-size大小如下:
deviceWidth = 320,font-size = 320 / 6.4 = 50px deviceWidth = 375,font-size = 375 / 6.4 = 58.59375px deviceWidth = 414,font-size = 414 / 6.4 = 64.6875px deviceWidth = 500,font-size = 500 / 6.4 = 78.125px
事实上网易就是这么干的,你看它的代码就知道,body元素的宽是:
根据这个可以肯定它的设计稿竖着时的横向分辨率为640。然后你再看看网易在分辨率为320*680,375*680,414*680,500*680时,html的font-size是不是与上面计算的一致:
320*680
375*680
414*680
500*680
这个deviceWidth通过document.documentElement.clientWidth就能取到了,所以当页面的dom ready后,做的第一件事情就是:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';
这个6.4怎么来的,当然是根据设计稿的横向分辨率/100得来的。下面总结下网易的这种做法:
(1)先拿设计稿竖着的横向分辨率除以100得到body元素的宽度:
如果设计稿基于iphone6,横向分辨率为750,body的width为750 / 100 = 7.5rem 如果设计稿基于iphone4/5,横向分辨率为640,body的width为640 / 100 = 6.4rem
(2)布局时,设计图标注的尺寸除以100得到css中的尺寸,比如下图:
播放器高度为210px,写样式的时候css应该这么写:height: 2.1rem。之所以取一个100作为参照,就是为了这里计算rem的方便!
(3)在dom ready以后,通过以下代码设置html的font-size:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';
6.4只是举个例子,如果是750的设计稿,应该除以7.5。
(4)font-size可能需要额外的媒介查询,并且font-size不能使用rem,如网易的设置: