首先要搞清楚几个概念
- 物理像素(physical pixel):手机屏幕最小的物理显示单元,即分辨率750×1334,横向750个,纵向1334个
- 设备独立像素–CSS像素 ,一个CSS像素占用一个物理像素,dpr=1,一个CSS像素占用2个物理像素,dpr=2
- dpr:设备像素比(device pixel ratio):物理像素 / 设备独立像素 // 在某一方向上,x方向或者y方向,在javascript中,可以通过window.devicePixelRatio获取到当前设备的dpr。
视口
- 布局视口:浏览器厂商定的视口大小,一般768px ~ 1024px 查看方法: document.documentElement.clientWidth
- 视觉视口:是用户正在看到的网页的区域,大小是屏幕中CSS像素的数量。
window.innerWidth/Height返回视觉视口的尺寸 - 理想视口:布局视口明显对用户是不友好的,完全忽略了手机本身的尺寸,理想视口即屏幕的宽度
screen.width/height返回理想视口的尺寸,有严重的兼容性问题—可能返回两种值:
用三星S5实际测试,screen.width,设备内置浏览器显示的是360,下载的浏览器,uc,显示的是 1080
常见的适配方法:
固定高度,宽度自适应:垂直方向用定值,水平方向用百分比、定值、flex都行。这样设置之后,我们就可以不用管手机屏幕的尺寸进行开发了。缺点 是会感觉横向拉伸或压缩,优点是兼容性不错
方法:使用了完美视口:1
<meta name="viewport" content="width=device-width,initial-scale=1">
利用 rem 布局(完美适配解决方案):目前一般根据iphone6的屏幕宽度设定rem的值(即 html 的 font-size),然后根据页面宽度计算调整rem的值,适配各种屏幕。利用该方案,还可以根据 devicePixelRatio 设定 initial-scale 来放大 viewport,使页面按照物理像素渲染,提升清晰度。
优点:清晰度高,能达到物理像素的清晰度。 能解决 DPR 引起的“1像素”问题。 向后兼容较好,即便屏幕宽度增加、PPI 增加该方案依旧适用。
缺点:适配 js 需尽可能早进入,减少(避免)viewport 变化引起的重绘。 某些Android机会丢掉 rem 小数部分。 需要预编译库进行单位转换。 由于部分安卓机不允许缩放,所以安卓机全部放弃高清适配即安卓设置initial-scale=1
rem适配详细方法
首先,gulp管理工程,配置自动编译less。如果美工给的psd是640的宽度,那么mobileAdapt.js中计算rem的时候就除以10得到rem值
1
rem = docEl.clientWidth * dpr / 10;
相应的,在编写样式表的less文件中,开头定义一个计算rem的基数,该基数值为@ppr: 64px/1rem;
- 如果美工给的psd宽度是750,那么js中除以10,less中的基数设置为@ppr:75px/1rem。(6410=640,7510=750,懂了吧)
- 这样配置,写less样式的时候,按照psd中的宽度,间距,直接写px实际值作为单位,但是,需要除以@ppr。比如,psd中宽度是640px,那么,less里面就写640px/@ppr。编译less之后,你写的宽度会被自动转化成rem的值(我的方案只是用了一个除法单位换算的小技巧而已)。
总结
实际上做了这几件事情:
- 动态生成 viewport
- 屏幕宽度设置 rem的大小,即给设置font-size
- 根据设备像素比(window.devicePixelRatio)给设置data-dpr(css hack用),1和3都是为了适应高清屏幕
示例源码
本文中适配方案参考自阿里的移动端适配方案,本文示例源码