- 以下方法为px自动转换rem,顾名思义,配置完成后,不用再关心rem换算等等,只需按照设计稿的px值写入即可,当你保存后
PostCSS
插件会自动将px转换成所配置的rem值,并且你在浏览控制台观测界面时你会发现你在代码里写的是px单位,在控制台被转换成了rem单位。 - postcss 一种对css编译的工具,本身不会对css一顿操作,它通过插件实现功能。
1. 使用amfe-flexible + postcss-pxtorem
包实现px自动转换rem
1.1 首先下载需要的npm包
npm i amfe-flexible // 用于设置 rem 基准值
npm install postcss-pxtorem -D // 是一款 postcss 插件,用于将px单位转化为 rem
需要注意的是:
- 该插件不能转换行内样式中的 px,例如 <div style="width: 200px;"></div>
1.2 对文件进行额外的配置
- 首先在
mian.js
引入amfe-flexible
import 'amfe-flexible'
-
在与src文件夹平级区域创建一个为
.postcssrc.js
的文件
-
对
.postcssrc.js
文件进行额外配置
autoprefixer 是一个自动添加浏览器前缀的 PostCss 插件,browsers
用来配置兼容的浏览器版本信息,但是写在这里的话会引起编译器警告。因为 VueCLI 内部已经配置了 autoprefixer 插件。
/**
* PostCSS 配置文件
*/
module.exports = {
// 配置要使用的 PostCSS 插件
plugins: {
// 配置使用 autoprefixer 插件
// 作用:生成浏览器 CSS 样式规则前缀
// VueCLI 内部已经配置了 autoprefixer 插件
// 所以又配置了一次,所以产生冲突了
// 'autoprefixer': { // autoprefixer 插件的配置
// 配置要兼容到的环境信息
// browsers: ['Android >= 4.0', 'iOS >= 8']
// },
// 配置使用 postcss-pxtorem 插件
// 作用:把 px 转为 rem
'postcss-pxtorem': {
// lib-flexible 的 REM 适配方案:把一行分为 10 份,每份就是十分之一
// 所以 rootValue 应该设置为你的设计稿宽度的十分之一
// 我们的设计稿是 750,所以应该设置为 750 / 10 = 75
// 但是 Vant 建议设置为 37.5,为什么?因为 Vant 是基于 375 写的
// 所以必须设置为 37.5,唯一的缺点就是使用我们设计稿的尺寸都必须 / 2
// 有没有更好的办法?
// 如果是 Vant 的样式,就按照 37.5 来转换
// 如果是 我们自己 的样式,就按照 75 来转换
// 通过查阅文档,我们发现 rootValue 支持两种类型:
// 数字:固定的数值
// 函数:可以动态处理返回
// postcss-pxtorem 处理每个 CSS 文件的时候都会来调用这个函数
// 它会把被处理的 CSS 文件相关的信息通过参数传递给该函数
// file : vant-button.css
// file : login.vue
mediaQuery: false, //媒体查询( @media screen 之类的)中不生效
minPixelValue: 12, //px小于12的不会被转换
// unitPrecision: 5, //保留rem小数点多少位
// selectorBlackList: [''], //则是一个对css选择器进行过滤的数组,比如你设置为['fs'],那例如fs-xl类名,里面有关px的样式将不被转换,这里也支持正则写法。
rootValue({ file }) {
return file.indexOf('vant') !== -1 ? 37.5 : 75 // 此处是以375为基准进行计算 1rem相当于37.5px
},
rootValue: 37.5, // 或者直接指定所有的都为37.5 二选一
// 配置要转换的 CSS 属性
// * 表示所有
propList: ['*']
}
}
}
-
上效果图
- 可以明显看到,代码中用的是px单位,经过配置px单位在界面上被自动转换成了rem值
- 但安装好可能会报:PostCSS plugin postcss-pxtorem requires PostCSS 8.
// 去到package.json文件查看postcss-pxtorem的版本,因为就是它的版本过高了,所以导致这个问题的出现
// 你只需要把的版本降低到5.1.1就OK了
npm i postcss-pxtorem@5.1.1
2. 使用autofit.js
-- 比较推荐
- 下载包
npm i autofit.js
- 引入
~ App.vue
import autofit from 'autofit.js'
// 需要在renderDom挂载到dom之后,才可以生效
export default {
mounted() {
autofit.init({
designHeight: 1080, // 设计稿的高度,默认是 929 ,如果项目以全屏展示,则可以设置为1080
designWidth: 1920, // 设计稿的宽度,默认是 1920
renderDom:"#app", // 渲染的dom,默认是 "#app",必须使用id选择器
resize: true // 是否监听resize事件,默认是 true
})
},
}
3. 用js配置+vscode扩展处理适配问题
2.1 在项目内创建一个js文件里面写入如下代码
(function flexible (window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10 //此处修改等分份数,现在是37.5px一份(以375设计稿为标准)
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// 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)
}
}(window, document))
- 是不是觉得这串代码很熟悉,这个js文件原名为
flexible.js
,不懂的可以自行百度下,这是个立即执行函数,所以不用担心执行时机。
2.2 在main.js
进行引入||局部引入也可以
import '@/utils/flexible'
2.3 使用vscode扩展辅助计算
- 装好之后来看下如何使用,我们已经在js文件内进行了配置,把界面进行了10等分,每份37.5px(以375设计稿为标准)
-
设置px2rem扩展自动计算的基准值
- 当你点击扩展设置后,将红框里面的值换成现在的基准值(例如现在的基准值是37.5)
-
注意:修改完扩展参数后需要重启编辑器才会生效哦
-
使用时直接输入对应的px像素值,此时就会提示出转换rem后的选项,并且后面还加了注释,第一个代表现输入的像素值第二个代表基准值。完全不用担心第二天来了,看见这么多rem单位一脸懵的问题。
4 获取页面元素动态计算页面展示倍数
<template>
<div id="app">
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view />
</div>
</template>
<script>
export default {
mounted() {
window.onresize = () => {
return (() => {
this.$nextTick(() => {
setScale();
});
})();
};
function setScale() {
let designWidth = 1920; //设计稿的宽度,根据实际项目调整
let designHeight = 1080; //设计稿的高度,根据实际项目调整
let dom = document.querySelector("#app");
if (dom) {
dom.style.transform = `scale(${
document.documentElement.clientWidth / designWidth
}, ${document.documentElement.clientHeight / designHeight})`;
dom.style.transformOrigin = "left top";
dom.style.width = "1920px";
dom.style.height = "1080px";
} else {
setTimeout(() => {
setScale();
}, 500);
}
}
setScale();
},
};
</script>
<style lang="less">
* {
padding: 0px;
margin: 0px;
}
body,
html {
height: 100%;
width: 100%;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>