通过淘宝的flexible进行适配
- viewport
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale: 1.0"
>
老版本flexible.js会修改scale值,会产生一些问题。
- 计算rem
var docEl = document.documentElement
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
clientWidth是根元素的可视宽度,如果viewport缩放scale=1.0,那么对于iPhone4的clientWidth=320px,如果scale=0.5,那么clientWidth=640px,无论如何改变viewport值,rem都等于根节点可视宽度的1/10。
老版本0.3.2里有这样一段。
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
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;
通过设备dpr,动态更新scale。这种方式并不影响rem的计算,好处是解决了1px的问题,坏处是破坏了css媒介media。
新版本2.0里面则去掉了动态计算scale的方式,改为检测是否支持0.5px的特性,通过添加类名hairlines来向下兼容
// 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)
}
如何实现从px到rem单位的转换
1. 通过编译器设置1rem的值,开发过程中编译器会自动将px转为rem
- 优点:使用方便,不需用通过其他方式转换
- 缺点:不利于后期代码维护
2. 利用sass函数来转换单位
@function pxTorem($px){ //$px为需要转换的字号
@return $px / $browser-font-size * 1rem; //100px为根字体大小
}
.first{
font-size: pxTorem(100px);
height: pxTorem(10px);
width: pxTorem(200px);
}
3. 借助webpack,px2rem-loader实现
下载loader
npm install style-loader css-loader px2rem-loader --save-dev
4. 借助PostCSS的px2rem插件
下载loader
npm i postcss-px2rem --save-dev
移动端REM适配原理总结:
-
设计稿的像素单位px,称之为
CSS像素。 -
我们需要百分百还原设计稿,就是要按照设计稿的比例,
一比一还原到设备上。 -
首先,每台移动设备都有自己的
物理像素和设备独立像素,它们之间的关系称之为DPR(device pixel ratio)。即DPR = 物理像素 / 设备独立像素。 -
iPhone公司为了吸引用户,引入了retina屏幕的概念,即在手机尺寸变化的情况下,DPR为2或者3。就是就是
每一个设计独立像素,都会占用4个物理像素点或9个物理像素点。 -
然后,我们说说视口和缩放比的概念,视口分为
布局视口,视觉视口和理想视口,以及设备缩放比。 -
布局视口是指我们开发出来的页面占据多少设备独立像素,当然超过手机宽度(即视口宽度)会出现页面滚动。 -
视觉视口就是我们当前可以看到的手机屏幕窗口大小。 -
先说
设备缩放比,类似于我们用放大镜看书本上的东西,放大意味着我们看到的文字大内容少。缩小意味着我们看到的文字小内容多,跟这里是一个道理。比如,设置设置缩放比为0.5,即手机可以看到之前4倍多的像素内容。我们可以通过meta标签对viewport进行缩放比设置。 -
理想视口就是在设备缩放比为1的情况下,布局视口和视觉视口大小相等,我们不需要去通过滚动条去看更多的隐藏内容。一般情况下我们可以设置
width=device-width,即布局视口和视觉视口相等。 -
再说
flexible.js,flexible做了一件事,就是给根节点html设置字体大小,因为rem是相对于html的字体大小的单位,1rem = html的字体大小。 -
老版本的flexible在没有对viewport进行设置视,它会
动态设置viewport,同时修改设置缩放比。这样虽然可以正常地解决适配问题,但是带来另一个问题是:破坏了css媒介media。 -
css媒体查询media取到的值其实就是设置独立像素,修改设备缩放比会修改掉设备独立像素的值。因此flexible优化了这里。
-
新版本的flexible.js采用了写死viewport的方式,
不会动态修改meta和设备缩放比。这样就避免了上边对media的破坏,也很好的解决了适配问题。新增了检测是否支持0.5px的特性。 -
最后说说rem单位,rem单位其实就是通过,把视口宽度等分为十等分(因为视口宽度一般是320px,360px,375px,414px,为了计算相对方便,取十等分)。比如320px十等分,1rem = 32px,这样我们写CSS的时候,如果设计稿上某元素的宽是64px,其实就是2rem。
-
但是,为了开发高效,我们不可能对每个尺寸都手动去转rem。因此就需要通过以上四种方式去自动转rem,来提升开发效率。