说到移动端适配,首先咱们须要先搞清楚一些基础知识,因此本文路线是先了解像素,dpr,视口等基础知识,而后再整理出移动端适配方案。php
像素其实分为两种,分别是物理像素和CSS像素html
视口也叫做初始包含块,之因此叫这个名字,是由于它包含了元素,它的宽度是全部CSS百分比宽度推算的根源。
在桌面浏览器,视口的宽度等同于浏览器窗口的宽度,高度即为浏览器窗口的高度。但移动端就有点复杂了,移动端的视口分为布局视口和视觉视口。git
设置布局视口宽度:<meta name="viewport" content="width=640"> 获取布局视口宽度:document.documentElement.clientWidth
布局视口除了和meta设置的width有关,还和scale有关,scale后面会说。github
获取视口宽度:window.innerWidth/Height
初始状态下,通常视觉视口会等于布局视口。web
实现方法:<meta name="viewport" content="width=device-width">(即设置布局视口宽度为设备宽度)
原理:能够理解为修改dppx,举个例子,假设一屏幕DPR为2,即1px对应2pt,若是这个时候,咱们设置scale=0.5,那么dppx就会从2变成1,即1px对应1pt。因此,经过缩放咱们能够调整本身所能控制的最小物理像素粒度。
缩放会影响布局视口的大小,由于浏览器会尽可能让布局视口铺满屏幕,因此当咱们设置scale=0.5时,布局视口的宽度会自动变为原来的两倍。
具体以下图所示。
浏览器
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <script> console.log(document.documentElement.clientWidth); //结果为375 </script>
<meta name="viewport" content="width=device-width,initial-scale=0.5"> <script> console.log(document.documentElement.clientWidth); //结果为750 </script>
可能有人会问,scale的初始值是多少?其实这取决于viewport的宽度,由于浏览器会尽可能让布局视口铺满全屏,因此浏览器会根据布局视口的大小动态调整scale的初始值大小,从而使布局视口铺满全屏。
使用缩放的好处:对于DPR为2或更高的屏幕,若是不作缩放操做,咱们所能控制的最小物理像素粒度是2pt或更多物理像素,这样带来了两个问题。wordpress
<style> #log { border: 1px solid black; } </style> <div id="log"></div>
解决这两个问题的方法就是缩放,咱们把scale设置为1/dpr。布局
meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
这样1px就对应1pt,咱们就能够解决1px border问题和图片的高清问题了。flex
<meta name="viewport" content="width=device-width,initial-scale=1">
适合场景:比较适合列表式的结构。优化
<meta name="viewport" content="width=640">
这个时候会发现,浏览器会帮助咱们将页面铺满全屏,并且这是绝对的等比例缩放。图片、文字等等全部元素都被缩放在手机屏幕中。
rem作宽度,viewport缩放
根据屏幕宽度设定rem值,须要适配的元素都使用rem为单位,不须要适配的元素仍是使用 px 为单位。
总共分两步:
document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';
meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
第二步是对页面适配的优化,修改scale是为了解决前面说到的1px border问题。
淘宝的Flexible使用的就是这种方案,并且它加了data-dpr属性,这样咱们就能够根据不一样的DPR设置不一样的样式。
方案一比较适合列表这种比较固定的结构,方案二适合的场景比较多,并且实现简单,但须要注意它会将页面的全部元素都缩放,方案三适合的场景是页面内有些元素须要适配,有些元素不须要适配。整体来说,方案二和方案三是比较经常使用的方式。
参考文献:
https://www.zybuluo.com/gongzhen/note/170557
郑航的知乎回答https://www.zhihu.com/question/35221839
https://github.com/amfe/article/issues/17
https://github.com/riskers/blog/issues/18
https://riskers.github.io/share/share/flexible.htm#1
https://github.com/riskers/blog/issues/17
https://github.com/amfe/lib-flexible
http://www.html-js.com/article/2402
http://www.alloyteam.com/2016/03/mobile-web-adaptation-tool-rem/
https://www.nihaoshijie.com.cn/index.php/archives/593
http://www.zhangxinxu.com/wordpress/2012/08/window-devicepixelratio/