一、第一种方式是比较简单的,开发速度也比较快。主要利用-webkit-transform:scale()这个属性,比较设计稿和当前屏幕的宽度,或者高度,亦或者取两者的最小值,来进行自适应。
1. 如果宽度自适应,如果兼容iphoneX的话,此时的设计稿的背景图需要延长至1448,内容放在1206内,然后可以把背景图设在一个宽高100%的容器内,background-size:100% auto,需要进行宽度自适应的内容统一放在一个容器内,居中,然后用js统一缩放这个容器,已达到自适应的效果;
2. 如果高度自适应,兼容iphoneX的设计稿需要调整成1218*936,内容放在629中间,进行高度自适应缩放。
3.还有一种就是取两者的最小的那个来自适应。原理同上。
二、 比较简单的页面适配
比如顶部与底部的bar不管分辨率变化,高度和位置不变,中间的内容不管分辨率怎么变,都会位于左右两边等这种简单的布局的开发原则是:
1、文字流式(使用文字随着窗口变化自动换行)
2、控件弹性(flex布局)
3、图片等比缩放等。
三、 网易的做法
动态计算html根元素的font-size,进而通过rem进行适配。
如果设计稿横向分辨率是640px,为了计算方便,取100px的font-size为参照,那么body元素的宽度可以设置为6.4rem,于是html的font-size=deviceWidth / 6.4 ,这个deviceWidth就是viewport设置中的那个deviceWidth。这样不同分辨率计算结果如下:
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
同理,如果设计稿是750,则font-size=deviceWidth / 7.5,
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
这样的话,比如一个元素高度是210px,则height:2.1rem。
在dom ready后,需要通过以下代码动态设置font-size:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';//设计稿640
document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px'; //设计稿750
然后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} }
如果采用这种方式,视口要如下设置。
<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">
当deviceWidth大于设计稿的横向分辨率时,html的font-size始终等于横向分辨率/body元素宽。
之所以这么干,是因为当deviceWidth大于640时,则物理分辨率大于1280(这就看设备的devicePixelRatio这个值了),应该去访问pc网站了。事实就是这样,你从手机访问网易,看到的是触屏版的页面,如果从pad访问,看到的就是电脑版的页面。如果你也想这么干,只要把总结中第三步的代码稍微改一下就行了:
var deviceWidth = document.documentElement.clientWidth; if(deviceWidth > 640) deviceWidth = 640; document.documentElement.style.fontSize = deviceWidth / 6.4 + 'px';
var deviceWidth = document.documentElement.clientWidth; if(deviceWidth > 750) deviceWidth = 750; document.documentElement.style.fontSize = deviceWidth / 7.5 + 'px';
三、淘宝的做法
淘宝的做法和网易类似,也是使用了rem这个单位。通常采用如下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。淘宝触屏版布局的前提就是viewport的scale根据devicePixelRatio动态设置:
1、在devicePixelRatio为2的时候,scale为0.5
2、在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,这一点跟网易是一样的。
5、跟网易一样,淘宝也设置了一个临界点,当设备竖着时横向物理分辨率大于1080时,html的font-size就不会变化了,原因也是一样的,分辨率已经可以去访问电脑版页面了。
淘宝开源的解决方案:https://github.com/amfe/lib-flexible
代码如下:
(function flexible (window, document) { var docEl = document.documentElement var dpr = window.devicePixelRatio || 1 // adjust body font size function setBodyFontSize () { if (document.body) { document.body.style.fontSize = (12 * dpr) + 'px' } else { document.addEventListener('DOMContentLoaded', setBodyFontSize) } } setBodyFontSize(); // set 1rem = viewWidth / 10 function setRemUnit () { var rem = docEl.clientWidth / 10 docEl.style.fontSize = rem + 'px' } setRemUnit() // reset rem unit on page resize window.addEventListener('resize', setRemUnit) window.addEventListener('pageshow', function (e) { if (e.persisted) { setRemUnit() } }) // detect 0.5px supports if (dpr >= 2) { var fakeBody = document.createElement('body') var testElement = document.createElement('div') testElement.style.border = '.5px solid transparent' fakeBody.appendChild(testElement) docEl.appendChild(fakeBody) if (testElement.offsetHeight === 1) { docEl.classList.add('hairlines') } docEl.removeChild(fakeBody) } }(window, document))
开发步骤:
第一步,视觉设计阶段,设计师按宽度750px(iPhone 6)做设计稿,除图片外所有设计元素用矢量路径来做。设计定稿后在750px的设计稿上做标注,输出标注图。同时等比放大1.5倍生成宽度1125px的设计稿,在1125px的稿子里切图。
第二步,输出两个交付物给开发工程师:一个是程序用到的@3x切图资源,另一个是宽度750px的设计标注图。
第三步,开发工程师拿到750px标注图和@3x切图资源,完成iPhone 6(375pt)的界面开发。此阶段不能用固定宽度的方式开发界面,得用自动布局(auto layout),方便后续适配到其它尺寸。
第四步,适配调试阶段,基于iPhone 6的界面效果,分别向上向下调试iPhone 6 plus(414pt)和iPhone 5S及以下(320pt)的界面效果。由此完成大中小三屏适配。
注意第三步,就要使用我们以上介绍的网易跟淘宝的适配方法了。假如公司设计稿不是基于750的怎么办,其实很简单,按上图做一些相应替换即可,但是流程和方法还是一样的。解释一下为什么要在@3x的图里切,这是因为现在市面上也有不少像魅蓝note这种超高清屏幕,devicePixelRatio已经达到3了,这个切图保证在所有设备都清晰显示。
来源:https://www.cnblogs.com/liuzhixiang/p/9074712.html