rem方案原理
rem方案的原理其实就是,将每一个不同的屏幕划分成相同的份数,让同一个元素在不同的屏幕上占据相同比例的空间。1rem等于此页面html的font-size,rem可以理解为每份是多少px,比如说,我们的设计稿宽度为750px,我们规定将页面划分成10份,那么rem=75px,如果有一个div宽度为75px,就刚好为1rem。即,将750px宽的屏幕划分为10份,这个div宽度占一份。那么只需要让此div在不同宽度的屏幕下宽度都占一份,就行了。那么我们只需要做一件事,就是确定不同的屏幕下一份有多宽,即不同设备下1rem等于多少px?这很容易计算,document.body.clientWidth / 10
就能算出来。
通过这个式子很清楚地看到,核心思想就是把不同的屏幕划分成相同的份数,在设计稿中占一份的,在所有设备屏幕上都应该占一份。
rem的工程化实践
在实际开发工程时,我肯定不想去把设计稿里的元素一一计算转成rem,然后在代码里写width: xxx rem
,我还是希望直接写设计稿里标注的px,然后由工具自动转成rem去适配所有设备。
这里介绍两个npm package,1. lib-flexible,2.在postccs里使用postcss-pxtorem。
lib-flexible很简单,源码只有40行,它就是规定不论什么设备,都把宽度分成10份,并且设定了html的font-size。
var docEl = document.documentElement
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
而postcss-pxtorem,是postcss的一个插件,在处理css时自动将手写的px转成rem,配置项可以去看文档:
'postcss-pxtorem': {
rootValue: 75, //设计稿的rem
propList: ['*']
}
这样一来,pxtorem这个插件会自动将我们写的css中的px转成相对于750px尺寸设计稿的rem单位了。
告别rem,使用vw
lib-flexible的GitHub已经宣布停止使用rem方案了,因为找到了新的更好的全局性参照单位:vw。
什么是 vw ?同样根据CSS Values and Units Module Level 4:(vw)等于初始包含块(html元素)宽度的1%。换句话说,可以认为: 1vw 就等于屏幕宽度的1% 。这个单位似乎是专门为我们适配量身打造的。首先,它本质上就是一个百分比单位,比如 3vw 就相当“屏幕宽度的百分之三”;其次,它又是全局性的与屏幕宽度直接相关的单位。那么上一节概念阐述中举的两个百分比的例子,用 vw 单位可以直接写成:75px = 75/750 = 10vw,即占页面宽度的10%。
那么移动浏览器对 vw 的支持度如何呢?根据caniuse.com:
即 iOS 8+和 Android 4.4+都支持 vw ,而目前的手机应用通常支持iOS 9+和Android 5+。所以,实践中使用 vw 单位完全可行。而这也正是手机淘宝团队19年初正式转向使用 vw 单位适配的原因。
那么,还是之前的问题,人工进行设计稿的 px 到 vw 单位的转换太麻烦。在开发中使用Webpack编译打包,那么已经有人开发了postcss的插件:postcss-px-to-viewport。配置好这个插件,你写CSS的时候可以严格按照设计稿上的像素值去写,这个插件负责将你写的 px 转换为 vw 。