px
px是CSS像素,是逻辑像素,在不同屏幕上对应不同的物理像素点。比如iphone6的逻辑分辨率是375*667,物理分辨率是750*1344,iphone6上,documet.body.clientWidth 得到的值是375,因此是二倍屏,用两个物理宽度表示一个逻辑宽度。
rem
rem是相对单位,以页面html的font-size为参照物,如果html上的font-size=16px,那么1rem = 16px。px转rem后需要动态设置html上的font-size。
转换可以使用postcss-pxtorem插件,设置基准值,基准值用来做单位转换,如果设定基准值rootValue=100,然后有个div的宽度50px,那打包产物里就是50px/基准值=0.5rem。
postcss
postcss-pxtorem是postcss的插件,postcss会把css转换成ast语法树,同时提供了一些遍历的方法:
walkAtRules:遍历所有的atRule,比如 @media
walkComments:遍历所有注释
walkDecls:遍历所有属性
walkRules:遍历所有css代码块
假如一个CSS如下
.card {
width: 100px
}
那通过walkDecls遍历得到node节点包含
{
prop: 'width',
value: '100px'
}
postcss-pxtorem
postcss处理后再传给的其插件处理,插件的入参是插件的options,出参是一个函数,该函数将被postcss调用,调用时会传入root参数。
const postcss = require('postcss');
module.exports = postcss.plugin('postcss-pxtorem', options => {
return (root, result) => {
root.walkDecls(decl => {
decl.value = decl.value.replace(/(\d+(\.\d+)?)px/g, ($0, $1) => {
return `${$1 / options.rootValue}rem`
})
})
}
})
plugins: {
'postcss-pxtorem': {
rootValue: 100, // 基准值
}
}
font-size设置
上面的50px经过处理得到0.5rem,这个0.5rem展示多宽,取决于页面html标签上的font-size。这个font-size需要注入js来动态设置。如果视觉稿宽度是750,屏幕宽度是375,则font-size = 375 / 750 * rootValue,这个时候0.5rem将会展示为25px。
rem本质上维护了一个比例关系,即font-size/rootValue = 屏幕宽度/视觉稿宽度。如果把rootValue设为1,那font-size直接就是屏幕宽度和视觉稿的比例了,相当于每个px从视觉糕到屏幕上都要乘以一个比例,这个比例在不同的屏幕宽度上是不一样的,需要动态设置。
font-size有多种设置方式:
1.js注入
const setRem = () => {
const rootValue = 100;
let clientWidth = document.documentElement.clientWidth;
document.documentElement.style.fontSize = rootValue *(clientWidth / 750)
}
window.addEventListener('resize', setRem, false);
document.addEventListener('DOMContentLoaded', setRem, false);
2.媒体查询
@media screen and (min-width: 375px) {
html {
font-size: 50px;
}
}
@media screen and (min-width: 750px) {
html {
font-size: 100px;
}
}
3.使用vw
但是使用这种方式,就完全没必要转rem了,直达px2vw即可。
html {
font-size: 13.3333vw;
}
vw/vh
vw/vh也是相对单位,屏幕宽度/高度百分比,屏幕高度宽度分别为100vw和100vh,比如20vw=屏幕宽度的20%,相比于rem方案,vw/vh具有不需要注入JS脚本的优势,有更好的兼容性。
postcss-px-to-viewport
转换可以使用postcss-px-to-viewport插件,假如视觉稿宽度是750,有个div宽度是50px,那打包后宽度是50px/视觉稿宽度750 = 0.06667vw,在375的屏幕上,0.06667vw会展示为0.06667vw*375=25px。
const postcss = require('postcss');
module.exports = postcss.plugin('postcss-px-to-viewport', options => {
return (root, result) => {
root.walkDecls(decl => {
decl.value = decl.value.replace(/(\d+(\.\d+)?)px/g, ($0, $1) => {
return `${parseFloat($1 / options.viewportWidth)}${options.viewportUnit}`
})
})
}
})
options配置
plugins: {
'postcss-px-to-viewport': {
viewportWidth: 750, // 设计稿宽度
viewportUnit: 'vw'
}
}