作移动端页面以来,常常会据说移动端的适配这个问题,可是并无认真分析过是如何适配各类机型的。目前公司用的是手淘的flexible.js进行页面适配的。适配的根本原理其实就是将设计稿按必定的比例在不一样的手机上实现。javascript
在分析移动段适配以前首先要了解一下rem, css3的一个相对长度单位。既然是相对长度,那就有一个参照体了,rem就是相对于html元素的font-size计算值的倍数。即1rem 等于一倍的html元素的font-size值。css
最先看到这个适配是在同事的代码里,当时并不知到是什么原理,也并不明白这些数字是怎么来的。
@media screen and (min-width:350px){ html{font-size:342%;} } @media screen and (min-width:360px){ html{font-size:351.56%;} } @media screen and (min-width:375px){ html{font-size:366.2%;} } @media screen and (min-width:384px){ html{font-size:375%;} } @media screen and (min-width:390px){ html{font-size:380.85%;} } @media screen and (min-width:393px){ /* 小米NOTE */ html{font-size:383.79%;} } @media screen and (min-width:410px){ html{font-size:400%;} } @media screen and (min-width:432px){ /* 魅族3 */ html{font-size:421.875%;} } @media screen and (min-width:480px){ html{font-size:469%;} } @media screen and (min-width:540px){ html{font-size:527.34%;} } @media screen and (min-width:640px){ html{font-size: 625%;} } @media screen and (width:720px){ html{font-size: 703.125%;} }
@media
媒体查询, 能够针对不一样的屏幕尺寸设置不一样的样式,特别是若是你须要设置设计响应式的页面,@media 是很是有用的。当你重置浏览器大小的过程当中,页面也会根据浏览器的宽度和高度从新渲染页面。
上述代码中,第一个@media screen and (min-width:350px)
表示当移动设备的宽度大于350px的时候页面将使用花括号内的样式,即将html根元素的字号设置为342%。(max-width:350px,则表示设备宽度小于350px时将采用此样式)。上述css代码的做用可见就是在不一样分辨率的设备上设置不一样的html字体大小。html
为何要这样设置呢?由于这种适配方法用的是css3的rem来进行适配的,而前面讲了,rem是相对于html的字号来计算的,如今不一样的设备上html的字号改变了,也就意味这1rem表明的px像素值不一样了,也就达到了按比例在不一样设备上适配同一个页面的效果了。java
html元素的font-size值又是怎么肯定的呢?拿下面的举例:css3
@media screen and (min-width:375px){ html{font-size:366.2%;} }
屏幕宽度大于375px的会按照宽度375px来适配。设计同时平时给咱们的设计稿通常是640px宽度或者750px宽度的,而咱们上面的都是假定设计稿是640px宽来计算的,750px也是同理计算。如今:web
1.屏幕宽度是375,设计稿宽度是640,ratio = 375/640=0.5859375;
2.咱们要将设计稿上元素用css单位rem写下来,那么该如何转换,1rem应该等于稿子上多少px。
这里咱们设定1rem = 100px ;能够设定其它值吗,固然能够,这里设置为100只是方便咱们在写css的时候好计算,小数点直接左移两位就能够了。好比,设计稿上一个宽46px按钮,这样转换成rem直接就是0.46rem。
3.如今1rem表明设计稿上100px,那么又该是等于设备上最后真实的多少像素呢。就要用到前面的屏幕宽度和设计稿的宽度比 ratio,设计稿上100px表明了真实的设备100*ratio = 58.59375px。
换句话说 css中写的1rem等于设备58.59375px。又由于1rem等于1倍的html元素的font-size,因此这里的html元素的font-size最终应该设置成58.59375px。可为何上述代码中用的是百分比呢?由于通常浏览器中html元素的默认字号都是16px,可是当用户放大或者缩小浏览器字号设置时,就不会是16px了,因此咱们将html的font-size仍是设置成百分比更好,即 58.59375/16= 366.2109375%,也就是上面例子中的366.2%了。segmentfault
其它的屏幕上也是同此道理计算出html的font-size值的。浏览器
@media + rem适配移动端还有一个不可少的条件就是要在head标签中写入一个meta标签。 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, minimum-scale=1">
;关于viewport的了解能够看这里。此标签的做用是让layout viewport = visual viewport,用户也不可缩放页面。app
flexible.js也是rem适配的,它是将设备分红10份,1rem等于1/10。分析其中部分代码:字体
var devicePixelRatio = win.devicePixelRatio; dpr = devicePixelRatio || 1; if (isIPhone) { // iOS下,对于2和3的屏,用2倍的方案,其他的用1倍方案 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3; } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){ dpr = 2; } else { dpr = 1; } } else { // 其余设备下,仍旧使用1倍的方案 dpr = 1; } scale = 1 / dpr; ...... ....... metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
win.devicePixelRatio
(简称dpr),即设备像素比(戳我了解)
上述代码当dpr(设备物理像素和设备独立像素比)为3时候,页面缩入1/3,dpr为2时,页面绽开2/1。
function refreshRem(){ var width = docEl.getBoundingClientRect().width; if (width / dpr > 750) { width = 750 * dpr; } var rem = width / 10; docEl.style.fontSize = rem + 'px'; flexible.rem = win.rem = rem; }
上述代码将1rem设置成了设备真实宽度的1/10,所以html根元素的fontSize也就是设备真实宽度的1/10,假如设计老铁们给的漂亮稿子是750px宽的,写scss时1rem也就应该等于75px,那边我么的scss文件能够这样写:
@function px2rem($px, $base: 75) { @return ($px / $base) * 1rem; } /* 稿子上量得某按钮宽60px,高20px */ .btn{ width:px2rem(60); height:px2rem(20); }
vw:viewport width(可视窗口宽度)
vh:viewport height(可视窗口高度)
vw和vh等详情能够点这里
1vw等于1%的设备宽度(设计稿宽度),1vh等于1%的设备高度(设计稿高度),这样看来vw,vh其它是最方便的,可是目前兼容性不是特别好。
因此只有在不须要考虑兼容的时候能够用这个相对最简便的适配方案了,好比一些混合开发里,app内的浏览器若是支持vw、vh,只在app内使用的页面就能够放心大胆的用了。像下面的
客户端内的右下角webview,一个小的PK对决页面,这里就是用的vw,vh进行适配的。
/*右下角窗口设计稿宽200px,高220px*/ @function px2vw($px, $base: 200) { @return ($px/($base/100)) + vw; } @function px2vh($px, $base: 220) { @return ($px/($base/100)) + vh; } /*头像宽42px,高42px*/ .avantar{ width:px2vw(42); heightx:px2vh(42); }
目前工做中用到的就是后面的两种适配方案了。手淘那个还有的地方看不懂,仍是本身太Low了,可是看不懂车不影响老司机开车。