基本一直都在作移动端的开发,rem布局也写了好久,不过对于实现的原理有些模棱两可的盲点,本身总结一下留着之后回顾。 本文分如下几个层面,主打用最最通俗的语言来阐述。css
iphone6尺寸是375*667,那给div设置宽度375px后,为何宽度不是充满屏幕呢? 代码以下:(为了方面看,我全截图吧)html
这是为何呢? 来看一下页面宽度是多少前端
viewport是什么?翻译过来就是视窗的意思,只不过在移动端,视窗稍微有点绕。在解释这个以前,不得不引出几个词汇,分别是物理像素(physical pixel),设备独立像素(density-indenpendent pixel),设备像素比(device pixel ratio),要怎么通俗理解这三个词呢? 容我找找网上的图。ios
手机屏幕显示图像的最小单元。上图中iphone4和3gs,一样大小尺寸状况下,iphone4明显画面细腻不少,这是为何?屏幕尺寸没变,分辨率提高,画面就细腻了,更通俗一点的就是iphone4用来显示图像的点更多了,把屏幕上的物理像素点想象成整齐排列的点阵,3gs有320 * 480个点而ip4有960 * 640个点。浏览器
若是把物理像素看作是负责显示图像的硬件的话,那么设备独立像素是什么呢?咱们平时写的css像素就是设备独立像素的一种了。而这1px的css像素,在不一样的手机倒是呈现不一样的,为何ip4画面细腻?就是人家用4个物理像素点来描绘一个css像素。iphone
也就是常说的dpr , dpr = 物理像素/设备独立像素(注意,是在某一方向的,x轴或者y轴) , 理解这个很重要,iphone6的dpr是2,iphonex的dpr是3。ide
dpr是2的状况下css画一个点,这个点是由4个物理像素点提供支撑的。画一条线的话,那这条线实际上是2排物理像素点支撑的。布局
同理,dpr是3的状况下css画一个点,这个点是由9个物理像素点提供支撑的。画一条线的话,那这条线实际上是3排物理像素点支撑的。字体
在移动端,视窗分为三种,分别为layoutviewport、visualviewport、idealviewport。能够先记住一个,idealviewport就认为是设备宽度就好,iphone6就是375,iphone6p 就是414 ,其他两个先看我下面例子吧。flex
window.devicePixelRatio : 查看设备dpr
document.documentElement.clientWidth : 查看layoutviewport宽度
window.visualViewport.width : 查看visualViewport宽度
window.innerWidth : 查看文档宽度
须要来个小结了:
默认是980 (针对ios)
设置缩放为1 宽度为设备宽度时:就是375(设备宽度)
设置缩放为2 宽度为设备宽度时:仍是375(设备宽度)
设置缩放为0.5 宽度为设备宽度时:是750(设备宽度的2倍)
layoutviewport 取设置的宽度或者visualviewport他们中的最大值
默认是980 (针对ios)
设置缩放为1 宽度为设备宽度时:就是375(设备宽度)
设置缩放为2 宽度为设备宽度时:是187.5(设备宽度一半)
设置缩放为0.5 宽度为设备宽度时:是750(设备宽度的2倍)
实际上是有公式的,visualviewport = 设备宽度/缩放。也就是visualviewport = idealviewport / initial-scale
顾名思义,是理想视窗意思,就是指的设备尺寸,主要用来和initial-scale配合,计算也就是visualviewport用的。
其实也是能够从名字就看出来的,layoutviewport布局视窗,visualviewport视觉视窗。 这里加个图,initial-scale = 1 width=devide-width,而后box宽度设置750px,发现html宽度在375,页面出现滚动条,而且,有意思的是,是按照375宽度排列的,只有那个设置了宽度是750的box宽度变大,因此layoutviewport负责布局,visualviewport负责视觉,是否是有了点直观印象了,以下图:
这里就更很差用语言描述了,有些抽象。回顾上文,知道iphone3gs iphone6 iphonex三者屏幕尺寸大小不一样,dpr的话,前二者是1 2 而 iphonex是3。那如何使得一张前端页面,在每一个手机看起来都是同样大呢?以iphone6和iphonex来举例,虽然屏幕宽度都是375,可是iphonex却拥有更加密集的物理像素点阵。iphone3gs更不用说,320的宽度,dpr又是1。 假若咱们规定,只用设备的物理像素,来绘制css的像素,要求一比一的绘制,那一张320px宽度的页面,在3个手机上的展现必定大体以下:
这只是一个示意图,也许并不精准。不过大致就是这样的,ip6宽度有着750个物理像素点,iphonex宽度有1125个物理像素点,因此根据上面的假想要求,画出来的必定是这样的。那么想要iphone6画出的这个320px的页面也充满屏幕的话,要怎么作?首先假如设置initial-scale=1, width=device-width,这种状况下,宽度375的iphone6画出宽度320px的前端页面大体什么样呢?
rem是什么,这个你们应该都清楚了。就是给html设置字体大小,假如是30px,那么页面中写了2rem那就是60px。 设计给出一张设计稿,页面宽度是750px,其中一个div标注了是宽度375px。如何作到在iphone6和iphonex中,看到的这个div都是屏幕宽度的一半呢?
相信你们都已经有答案了。
对于iphone6 设置initial-scale=0.5, width=device-width,而后就直接写375px就好 对于iphonex 设置initial-scale=1/3, width=device-width,而后就直接写(375*(3/2))px就好。 缺点就是须要咱们自行计算。
rem方案 : 设计稿750px,div标注375px,对于iphone6 设置initial-scale=0.5, width=device-width,若是html设置font-size为75px,那div咱们就直接写5rem就好了。而后适配到iphonex中时,不须要改变div的5rem,只需改变在iphonex中html的字体以及页面缩放,设置 iphonex中 initial-scale=1/3, width=device-width,而后设置html字体为112.5px,此时的5rem为562.5px,恰好是屏幕1125的一半。
上面关于rem适配已经思路实现,如今还差几个环节,就是为何设置iphone6是0.5缩放,iphonex是1/3缩放呢?而后又根据什么设置的html字体?
答: dpr 。那么又是怎么设置的?flexible.js就要登场了,flexible.js是手淘的前移动端适配解决方案,为何是前方案,由于目前浏览器对于vw vh支持的更加友好,这个后面再说。看看flexible.js作了什么吧,直接截图一些代码吧。
感受没什么好解释的,就是获取设备dpr,而后肯定scale嘛
而后把meta标签塞到html中
不过rem咱们本身来计算的话就很繁琐了,如给的iphone6,宽度750的设计稿,标注的375px,咱们就写375px就好,固然是写成px2rem(375)这样。
关于flexible.js的实现原理,我也就是挑重点的说了说,仍是建议你们去看大漠老师写的源码,一百多行代码而已,挺好的,也很容易看懂,不过要想清楚为何要那么作,就是我上面大篇幅写的东东啦~
关于vw vh实际上是将视口宽度 window.innerWidth 和视口高度 window.innerHeight 等分为 100 份,而且此时的视窗并不会随着 viewport 的不一样设置而改变。
vw : 1vw 为视口宽度的 1%
vh : 1vh 为视口高度的 1%
上面说的设计稿为 750px,那么 1vw = 7.5px,100vw = 750px。此时给的不是750设计稿也没所谓,假如给1000px的设计稿,那咱们写的1v我就是10px。其实这不就是rem作的事吗?只不过咱们用rem+flexible.js绕了一圈的感受
做为后面要补充的点吧,vw等我项目具体实操一波,再来补这个