移动端和PC端适配采用的方案,之前做大屏的时候设计稿是以1920*1080的尺寸设计的,考虑到市面上的显示其尺寸包括宽为1360、1440、1600、1660这几个尺寸,我在做适配的时候基本都是使用百分比和calc的方式做自适应,在PC端基本没有问题,实际的大屏分辨率也都是1920*1080的,所以一直都没有问题,这次大屏客户的屏幕是3840*2160的分辨率,是之前的2倍,显示效果可想而知,与设计相差太多,所以从新考虑了适配方案,采用postcss-px2rem的方案
前提:项目是使用官网的方式创建的vue2.0版本的项目
这个方案主要分两步:这两步是完全独立的过程但又互相影响
1、根据分辨率动态设置html的字体大小;
2、引入postcss-px2rem将css中的px转成rem;
html设置字体大小
有两种方式为根节点html动态设置字体大小,
第一种:使用lib-flexible.js设置
这个插件是淘宝团队开发的,主要应用于移动端,代码中有一段限制了字体动态设置的屏幕大小是540px,也就是说大于540px之后html的字体大小就不变了。
function refreshRem()
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = 540 * dpr;
}
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
所以在移动端可以直接引用这个文件
下载方式:执行yarn add lib-flexible
引入方式:在main.js中通过import 'lib-flexible'
引入
计算规则:他会给html设置字体大小为当前屏幕宽度除以10的大小,比如iphone手机的屏幕物理像素是375*667
,那html的字体大小就是37.5px
。
第二种:模仿lib-flexible自己写一个
lib-flexible只适用于移动端,所以PC端需要模仿flexible自己按需求写一个,网上有很多这种代码,思路都是根据浏览器可视区的大小动态设置根节点html的字体大小,我暂且把文件命名为rem.js
// 基础字体大小
const baseValue = 75
// 可视区的大小,移动端是屏幕的宽度,PC端是浏览器可视区的宽度
let clientWidth = 0
// 设计稿的宽度
const designWidth = 1920
// 设置 rem 函数
function setRem () {
// 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。
clientWidth = document.documentElement.clientWidth
const scale = clientWidth / designWidth
// 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
document.documentElement.style.fontSize = baseValue * scale + 'px'
}
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function () {
setRem()
}
这种方式更适用于PC端,baseValue可以随意调整,但要跟postcss插件配合使用
配置postcss-px2rem
把px转换成rem的工具有两个,一个是post-css2rem另一个是postcss-pxtorem,两个用哪个都行,但是我看postcss-px2rem五年没有跟新了,本着有新的不用旧的原则,我把px2rem换成了pxtorem,具体有啥区别我也不知道,反正效果就是把px转成rem,结果都一样
先说postcss-px2rem
下载方式: yarn add postcss-px2rem
配置方式:在跟目录下新建vue.config.js文件,复制下面代码上去
// 引入等比适配插件
const px2rem = require('postcss-px2rem')
// 配置基本大小
const postcss = px2rem({
// 基准大小 baseSize,需要和rem.js中相同
remUnit: 75
})
module.exports = {
lintOnSave:true,
css:{
loaderOptions:{
postcss:{
plugins:[postcss]
}
}
}
}
再说说postcss-pxtorem
下载方式: yarn add postcss-pxtorem@5.1.1
,我的项目执行yarn add postcss-pxtorem
默认下载的是6.0版本结果运行不起来,所以我降低了版本
配置方式:在跟目录下新建postcss.config.js文件,复制下面代码上去,或者在vue.config.js中像px2rem那么配置也是可以的
//在postcss.config.js中配置
module.exports = {
"plugins": {
"postcss-pxtorem": {
//换算基数,默认100,把根标签的font-size规定为1rem为50px,在设计稿上量出多少px直接在代码中写多少px
rootValue: 75,
//保留rem小数点多少位
unitPrecision: 5,
//存储将被转换的属性列表,'!font-size' 即不对字体进行rem转换
propList: ['*', '!border', '!font-size'],
//要忽略并保留为px的选择器,例如fs-xl类名,里面有关px的样式将不被转换,支持正则写法。
selectorBlackList: ['.radius'],
replace: true,
//(布尔值)媒体查询( @media screen 之类的)中不生效
mediaQuery: false,
//设置要替换的最小像素值,px小于12的不会被转换
minPixelValue: 12,
//默认值是一个空数组,这意味着禁用白名单并启用所有属性
//propWhiteList: [],
//黑名单
propBlackList: ['font-size'],
}
}
}
或者
//在vue.config.js中配置
// 引入等比适配插件
const pxtorem = require('postcss-pxtorem')
// 配置基本大小
const postcss = pxtorem({
//换算基数,默认100,把根标签的font-size规定为1rem为50px,在设计稿上量出多少px直接在代码中写多少px
rootValue: 75,
//保留rem小数点多少位
unitPrecision: 5,
//存储将被转换的属性列表,'!font-size' 即不对字体进行rem转换
propList: ['*', '!border', '!font-size'],
//要忽略并保留为px的选择器,例如fs-xl类名,里面有关px的样式将不被转换,支持正则写法。
// selectorBlackList: ['.radius'],
// 是否删除px的原有样式
replace: true,
//(布尔值)媒体查询( @media screen 之类的)中不生效
mediaQuery: false,
//设置要替换的最小像素值,px小于12的不会被转换
minPixelValue: 12,
//默认值是一个空数组,这意味着禁用白名单并启用所有属性
// propWhiteList: [],
//黑名单
// propBlackList: ['font-size'],
})
// 使用等比适配插件
module.exports = {
lintOnSave: true,
css: {
loaderOptions: {
postcss: {
plugins: [
postcss
]
}
}
}
}
这两个post插件的计算规则都是一样的,remUnit和rootValue的性质相同,转换规则就是将你页面的样式除以这个值,比如你页面的某个元素设置成宽度750px,那么除以这个值就会转换成10rem,这个值是不变的,不随浏览器可视区的宽度变化而变化,在1920的显示器上转成10rem,在1360的显示器上也转成10rem
lib-flexible与postcss如何配合使用
所以postcss需要跟flexible配合使用,我们先定义几个变量,然后缕清这几个变量之间的关系
clientWidth //屏幕的宽度
designWidth //设计稿的宽度
rootValue //postcss中配置的数值
baseValue //在自己编写的rem.js文件中的基础数值
以1920*1080尺寸的设计稿为例:假如页面有一个填满屏幕宽度的元素,元素的宽度就是designWidth
该元素通过postcss转化后的rem大小:designWidth/rootvalue
,无论屏幕如何缩放,该值是固定的
既然该值是固定的,那么实现适配就是通过动态改变html的字体大小实现的
首先计算缩放比,因为基础是1920的尺寸,在其他尺寸的屏幕就需要等比放大或缩小
缩放比:scale = clientWidth / designWidth
缩放比就是实际的屏幕宽度除以设计稿的宽度,如果实际宽度就是1920,那么scale就是1,即不缩放;如果实际屏幕是3840,那么scale就是2,即放大一倍
字体大小设置:baseValue * scale
也就是clientWidth / designWidth * baseValue
字体大小与post转化后的rem相乘就应该等于clientWidth,所以
(clientWidth / designWidth * baseValue)*(designWidth/rootvalue) = clientWidth
最后你会发现baseValue/rootvalue = 1
,也就是相等,所以在实际设置中,使用上述rem.js的计算方式,只要保证baseValue和rootvalue相等就可以了
如果上面的方法很难理解的话,有一种实践出真知的方式
就是放到浏览器中测试一下,比如我的设计稿是1920*1080的,那么我就把浏览器调到1920宽,然后看html的字体大小是多少,这个字体大小就是postcss中的rootValue的值,我现在rem.js中代码执行完html设置的大小是75px,那么我postcss中的rootValue大小就应该是75