一文搞懂pxtorem适配方案在项目中的使用方式和问题

704 阅读5分钟

最近在做屏幕适配,一套代码需要适配不同分辨率和不同缩放比例情况下的样式兼容

在实现的过程中遇到了这样几个问题:

  1. 为什么要用rem做适配?
  2. 按照之前vue cli脚手架的配置pxtorem方法进行配置,在webpack中不生效?
  3. 配置postcss-loader运行时会有报错,怎么解决?
  4. 行内样式写的px单位没有转化为rem,无法适配该怎么解决?

本文将会根据这几个问题进行汇总给出解决方案

为什么要用rem做适配?

要想了解为什么要用rem做适配就要先了解pxrpxrem 的特点和区别:

  1. px

    • px(像素) 是一个绝对单位,表示屏幕上的一个物理像素点。
    • 在不同的设备上,px 实际表示的大小是固定的,不考虑设备的分辨率或用户缩放设置。
    • 由于像素密度的差异,相同数量的 px 在不同的屏幕上可能会显示得更大或更小。
  2. rpx

    • rpx (responsive pixel) 是特定于微信小程序的响应式单位,用于适应不同宽度的屏幕。
    • 在微信小程序中,屏幕宽度为750rpx,因此1rpx等于屏幕宽度的1/750。
    • rpx 主要用于在不同宽度的手机上保持元素的相对大小一致。
  3. rem (根相对长度单位)

    • rem 是一个相对单位,相对于 HTML 根元素的字体大小。
    • 使用 rem 可以创建一个基于根元素字体大小的响应式布局,通过改变根元素的字体大小,可以影响整个页面的尺寸比例。
    • rem 适合用于响应式设计,因为它允许页面布局根据用户的默认字体大小或特定需求进行缩放。

总结:

  • px 适合用于需要固定像素精度的图像和布局。
  • rpx 特定于微信小程序,用于不同屏幕宽度的响应式设计。
  • rem 适合用于整个页面或组件的响应式布局,基于根元素字体大小。

我们开发的项目主要用在教室大屏和办公室大屏的特殊设备上,系统可以设置2k,3k,4k分辨率,而且还有可能会有缩放,如果要使用px,在设置不同的分辨率下样式会有错误,而使用%或者vw/vh计算会变得更复杂

pxtorem 使用方式

之前使用的是vue cli和vite脚手架搭建的项目,只需要按照官网的配置即可,但是目前做的是老项目,使用的是webpack,所以使用的方式还有些区别

vite/vue cli中的使用方式

安装配置

安装 postcss-pxtorem

npm install postcss postcss-pxtorem --save-dev

如果你是vue cli创建的项目就在 vue.config.js文件里进行配置;

如果是vite创建的项目就在 vite.config.js里进行配置

module.exports = {
  // 其他配置...
  css: {
    loaderOptions: {
      postcss: {
        plugins: [
          require('postcss-pxtorem')({
            rootValue: 15, // 换算的基数
            unitPrecision: 5, // 允许REM单位增长到的十进制数字
            propList: ['*'],
            selectorBlackList: [], // 要忽略并保留为px的选择器
            ignoreIdentifier: false,  // 忽略单个属性的方法
            replace: true, // 替换包含REM的规则,而不是添加回退。
            mediaQuery: false,  // 允许在媒体查询中转换px。
            minPixelValue: 0 // 设置要替换的最小像素值(3px会被转rem)。默认 0
          }),
        ]
      }
    }
  }
}

动态配置rem基数

动态调整 rem 基数可以根据屏幕宽度自动缩放页面元素,从而保持布局的一致性和适应性

新建rem.js

window.baseRootValue = 15; // 基准大小,作为行内样式rem调整处理。可统一调整
// 配置基本大小
let baseSize = window.baseRootValue || 15;
 
// 设置 rem 函数
function setRem () {
    //当前页面宽度相对于1920px屏幕宽的缩放比例,可根据自己需要修改。
    let scale = document.documentElement.clientWidth / 1920;
    //设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
    document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px'
}
setRem(); //初始化
 
// 适配 - 重置函数
function resetRem (num) {
    if(num) baseSize = Number(num);
    setRem();
}
window.resetRem = resetRem; // 全局可调用(其他方式也可)
 
// 改变窗口大小时重置 rem
window.onresize = function () {
    setRem()
};

在项目入口(一般都是在main.js)引入 rem.js文件

import './rem.ts';

这样就可以在页面使用px进行写样式了,运行程序会自动转化为rem

image.png

webpack中的使用 pxtorem

webpack中的使用 pxtorem 需要先安装postcss-loader和postcss-pxtorem

安装配置

npm install postcss-loader postcss-pxtorem --save-dev

webpack.config.js 文件中,配置 postcss-loader 以使用 postcss-pxtorem 插件。这通常在 module.rules 部分进行配置:

const path = require('path');

module.exports = {
  // ... 其他配置
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader"
        ],
      },
      {
        test: /\.less$/i,
        use: [
            'style-loader',
            {
                loader: 'css-loader',
                options: {
                    importLoaders: 1
                }
            },
            {
                loader: 'postcss-loader',
                options: {
                    postcssOptions: {
                        plugins: [
                            require('postcss-pxtorem')({
                                rootValue: 15, // 换算的基数
                                unitPrecision: 5, // 允许REM单位增长到的十进制数字
                                propList: ['*'],
                                selectorBlackList: [], // 要忽略并保留为px的选择器
                                ignoreIdentifier: false,  // 忽略单个属性的方法
                                replace: true, // 替换包含REM的规则,而不是添加回退。
                                mediaQuery: false,  // 允许在媒体查询中转换px。
                                minPixelValue: 0 // 设置要替换的最小像素值(3px会被转rem)。默认 0
                              }),
                        ]
                    }
                }
            },
            {
                loader: 'less-loader',
                options: {
                    lessOptions: {
                        javascriptEnabled: true
                    }
                }
            },
        ]
      },
    ],
  },
  plugins: [
    // ... 可能存在的其他插件
  ]
};

需要注意的是:因为loader的规则是链式处理,postcss-loader是处理css的,所以放在css之后,而不是less之后 这个顺序很重要,如果顺序错了,运行时就会报错

image.png

动态配置rem基数

动态配置rem基数和上面的一样,这里就不再废话

行内样式px转rem

postcss-pxtorem 插件无法处理 HTML 文件中的行内样式。postcss-pxtorem 主要是在构建过程中处理 CSS 文件和 <style> 标签中的样式。为了解决这个问题,可以手动计算rem值

  1. 通常,HTML 根元素(<html>)的字体大小被设置为一个基准值,比如 16px。这个值将作为 1rem 的基准。
  2. 要将 px 转换为 rem,你需要将 px 值除以根元素的字体大小(以 px 为单位)。例如,如果根元素的字体大小是 16px,则 1rem = 16px
  3. 对于任何给定的 px 值,使用上述比例进行转换。例如,如果一个元素的行内样式是 font-size: 32px;,则转换为 rem 是 font-size: 2rem;