移动端适配方案 : PostCSS px to viewport

移动端适配方案 - PostCSS px to viewport

问题描述

H5页面在小程序webview中显示时,部分机型(特别是iOS设备)出现缩放问题,字体变小等显示异常。

解决方案

方案一:PostCSS px-to-viewport(推荐)

使用 postcss-px-to-viewport 插件自动将px转换为vw单位,实现移动端适配。

1. 安装依赖
bash 复制代码
yarn add postcss-px-to-viewport --save-dev
2. 配置方案

方案A: 基于文件名判断转换(推荐)

vue.config.js 中添加配置:

javascript 复制代码
module.exports = {
  // ... 其他配置
  css: {
    loaderOptions: {
      postcss: {
        plugins: [
          require('postcss-px-to-viewport')({
            unitToConvert: 'px',
            viewportWidth: 375, // 设计稿宽度
            unitPrecision: 6, // 精确度
            propList: ['*'], // 需要转换的属性列表
            viewportUnit: 'vw', // 转换单位
            fontViewportUnit: 'vw', // 字体使用的单位
            selectorBlackList: ['.ignore', '.hairlines'], // 不转换的类选择器
            minPixelValue: 1, // 最小转换值
            mediaQuery: false, // 是否转换媒体查询
            replace: true, // 是否替换属性值
            exclude: [
              // 排除不需要转换的文件
              function(file) {
                // 只转换文件名包含 '_tovw' 的文件
                return !file.includes('_tovw')
              }
            ]
          })
        ]
      }
    }
  }
}

方案B: 基于目录判断转换

javascript 复制代码
module.exports = {
  // ... 其他配置
  css: {
    loaderOptions: {
      postcss: {
        plugins: [
          require('postcss-px-to-viewport')({
            unitToConvert: 'px',
            viewportWidth: 375,
            unitPrecision: 6,
            propList: ['*'],
            viewportUnit: 'vw',
            fontViewportUnit: 'vw',
            selectorBlackList: ['.ignore', '.hairlines'],
            minPixelValue: 1,
            mediaQuery: false,
            replace: true,
            exclude: [
              // 只转换特定页面
              function(file) {
                return !file.includes('market-chat')
              }
            ]
          })
        ]
      }
    }
  }
}
3. 使用方式

文件命名方式:

  • 需要转换的页面:index_tovw.vue
  • 不需要转换的页面:index.vue

目录方式:

  • 将需要将需要转换的目录添加到exclude配置中,如 market-chat/(包含页面+组件)
4. 样式写法

转换前(原始px):

css 复制代码
.container {
  width: 375px;
  height: 200px;
  font-size: 16px;
  padding: 20px;
}

转换后(自动生成vw):

css 复制代码
.container {
  width: 100vw;
  height: 53.333333vw;
  font-size: 4.266667vw;
  padding: 5.333333vw;
}

实施建议

1. 优先选择方案一的文件名判断方式

  • 优点:精确控制,不影响其他页面
  • 缺点:需要重命名文件

2. 配置参数说明

javascript 复制代码
{
  unitToConvert: 'px',      // 要转换的单位
  viewportWidth: 375,       // 设计稿宽度(根据实际设计稿调整)
  unitPrecision: 6,         // 精确度,保留6位小数
  propList: ['*'],          // 转换所有属性
  viewportUnit: 'vw',       // 转换为vw单位
  fontViewportUnit: 'vw',   // 字体也使用vw
  selectorBlackList: [],    // 不转换的类选择器
  minPixelValue: 1,         // 小于1px不转换
  mediaQuery: false,        // 不转换媒体查询中的px
  replace: true,            // 替换原值
  exclude: [/* 排除规则 */] // 排除文件规则
}

3. 注意事项

  1. 边框问题 :1px边框可能会被转换为很小的vw值,建议设置 minPixelValue: 2
  2. 字体最小值:避免字体过小影响阅读体验
  3. 图片适配:图片容器使用vw,图片本身使用百分比
  4. 第三方组件:需要添加到黑名单中

完整配置示例

javascript 复制代码
// postcss.config.js
const pxToViewport = require('postcss-px-to-viewport');

// VW转换状态控制
const enableVwTransform = process.env.ENABLE_VW_TRANSFORM !== 'false';
console.log(`📱 PostCSS VW转换: ${enableVwTransform ? '✅ 开启' : '❌ 关闭'}`);

module.exports = {
  plugins: [
    ...(enableVwTransform ? [
      pxToViewport({
        unitToConvert: 'px',
        viewportWidth: 375,
        unitPrecision: 6,
        propList: ['*'],
        viewportUnit: 'vw',
        fontViewportUnit: 'vw',
        selectorBlackList: ['.ignore', '.hairlines', '.el-'],
        minPixelValue: 1,
        mediaQuery: false,
        replace: true,
        exclude: [
          /node_modules/,
          // 通过文件夹配置 使用正则配置(仅移动端开启)
          /^(?!.*market-chat|.*_tovw).*$/,
        ]
      })
    ] : [])
  ]
}; 

在 package.json 中添加便捷脚本:

json 复制代码
{
  "scripts": {
    "serve": "vue-cli-service serve --mode dev",
    "serve:novw": "ENABLE_VW_TRANSFORM=false vue-cli-service serve --mode dev",
  }
}

配置说明

  • exclude使用正则配置,符合eslint编译要求;
  • 因为 market-chat 中的组件已经完成开发,为了不修改整个文件命名,使用指定文件夹匹配+文件命名匹配规则;
  • 后续使用推荐文件命名规则,例如:index_tovw.vue
  • 为了浏览器调试方便,通过配置启动命名动态开启vw转换,使用serve:novw启动保持px单位;
相关推荐
宇寒风暖3 小时前
@(AJAX)
前端·javascript·笔记·学习·ajax
Giser探索家8 小时前
低空智航平台技术架构深度解析:如何用AI +空域网格破解黑飞与安全管控难题
大数据·服务器·前端·数据库·人工智能·安全·架构
gnip9 小时前
前端实现自动检测项目部署更新
前端
John_ToDebug9 小时前
JS 与 C++ 双向通信实战:基于 WebHostViewListener 的消息处理机制
前端·c++·chrome
gnip9 小时前
监听设备网络状态
前端·javascript
As331001011 小时前
Chrome 插件开发实战:打造高效浏览器扩展
前端·chrome
xrkhy11 小时前
nvm安装详细教程(卸载旧的nodejs,安装nvm、node、npm、cnpm、yarn及环境变量配置)
前端·npm·node.js
德育处主任12 小时前
p5.js 3D盒子的基础用法
前端·数据可视化·canvas
前端的阶梯12 小时前
为何我的figma-developer-mcp不可用?
前端
weixin_4569042712 小时前
Vue3入口文件main.js解析
前端·javascript·vue.js