一句配置让你的小程序自动适应Pad端

序言

相信开发过小程序的朋友,都用过rpx这个单位,最近项目中在开发一款小程序,而在测试阶段发现,在Pad端的元素显示过大了,完全不适应Pad端,而业务上由于Pad端的使用者还是占多数的,所以需要实现Pad端的响应式。

问题

项目中都是使用rpx这个单位来布局的,用过这个小程序rpx单位都知道该特性:

简单来说,就是rpx将布局分成了750份,根据设置rpx的多少来布局,这样对应我们手机750的设计就很好的匹配适应,而在iPad端上,屏幕分辨率却是1536*2048,这样导致同样在手机端显示的文字大小,在iPad端会呈现2倍的效果。

方案

针对上述问题,我们很容易想到,那是不是在iPad端时,让元素的显示的大小减去一半就行了,比如

scss 复制代码
.rule {
    font-size: 20rpx;
}

// => iPad
.rule {
    font-size: 10rpx;
}

而判断iPad端的方式有两种:

  1. 根据UA是否带有pad字样进行判断;
  2. 根据媒体查询进行判断;

针对第一种,如果需要根据UA进行判断,就需要js进行判断再插入对应的className,这样不单每个页面都带重复写,还影响小程序性能,这样太过繁琐,所以我们采用了第二种方案。

通过媒体查询,我们在大于750px(pad端的dpr是2,所以这里是750)的情况,将rpx整体缩小一倍,如:

scss 复制代码
.rule {
    font-size: 20rpx;
}

// => iPad
@media (min-width: 750px) { 
    .rule {
        font-size: 10rpx;
    }
}

思考

虽然问题得到解决,但是每个页面组件都单独写媒体查询,依然太过复杂,那有没有根据简单的方法?

这里我想到了利用 postcss-plugin 在编译时对样式进行修改,大概思路如下

  1. copy一份原有的样式,将所有rpx对应缩小一半;
  2. 再用@media进行包裹,并插入到原样式后面(小程序媒体查询没有权重,所以要插入原样式之后,否则插入前面会更合理);

发布

基于想法,进行实现, @hsuna/postcss-media-query-transform 便孕育而生:

安装

shell 复制代码
npm i -D @hsuna/postcss-media-query-transform
yarn add -D @hsuna/postcss-media-query-transform
pnpm i -D @hsuna/postcss-media-query-transform

使用

  • 在postcss.config.js使用
js 复制代码
// postcss.config.js
module.exports = {
  plugins: [
    // for example
    // require('autoprefixer'),
    require("postcss-media-query-transform")({
      mediaQuery: { query: "(min-width: 750px)", scale: 0.5 },
      propList: ["*"],
      transformUnit: "rpx",
      insert: "after",
    }),
  ],
};

输入/输出

scss 复制代码
// input
.rule {
  margin: 0 0 20px;
  font-size: 2rpx;
  line-height: 1.2;
  letter-spacing: 0.0625px;
}

// output
.rule {
  margin: 0 0 20px;
  font-size: 2rpx;
  line-height: 1.2;
  letter-spacing: 0.0625px;
}

@media (min-width: 400px) {
  .rule {
    letter-spacing: 0.03125px;
  }
}

参数说明

  • 默认
js 复制代码
const defaultOptions = {
  mediaQuery: { query: "(min-width: 400px)", scale: 0.5 }, // 媒体查询及比例,允许多个
  unitPrecision: 5, // 保留位数
  selectorBlackList: [], // 不允许转化的选择器
  propList: ["font", "font-size", "line-height", "letter-spacing"], // 需要转化的样式 
  transformUnit: "px", // px | rpx | rem 需要转化的单位
  insert: "before", // before | after 需要拷贝的样式插入原样式的位置,默认之前
  exclude: [/node_modules/i], // 过滤的文件
  disabled: false, // 是否禁用该插件
};
  • 多个媒体查询
js 复制代码
const defaultOptions = {
  mediaQuery: [
      { query: "(min-width: 200px)", scale: 2 }, // 超过 200 缩放
      { query: "(min-width: 400px)", scale: 0.5 }
  ],
};
  • 小程序pad端自适应
js 复制代码
const defaultOptions = {
  mediaQuery: { query: "(min-width: 750px)", scale: 0.5 }, // 750px以上缩小一倍像素
  propList: ["*"], // 应用在所有像素上
  transformUnit: "rpx", // 使用在rpx单位
  insert: "after", // 小程序媒体查询没有权重,所以要插入原样式之后
};

插件其他效果

  • 对应转化后如果和原本样式一致的话,比如类似display:block;或者padding: 0;,那插件会将对这部分样式舍弃;
  • 针对@keyframes,如果所有过程都没有转化,则舍弃该@keyframes,否则保留所有@keyframes;
  • 如果样式原本就包裹在@media,则舍弃;

最后

虽然需求项目由于工期,我们还是采用了手写的方法去处理,但是后续的项目我们还是采用了该插件,目前线上效果挺好的~

相关推荐
lpfasd1238 小时前
node-sass 停止维护!老项目迁移 Dart Sass 完整教程
前端·rust·sass
Data analyse45610 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai10 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
环境栈笔记11 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
赵大仁11 小时前
官网性能优化实战:LCP 3.2s → 2.1s、CLS 0.107 → 0,以及被我推翻的 6 个判断
前端·性能优化·cls·lcp·core web vitals
xiancai_xianyu12 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架
小羊没烦恼!12 小时前
T-SQL查询进阶--理解SQL SERVER中的分区表
服务器·开发语言·前端·javascript·html
史瓦辛格12 小时前
给 DeepSeek Harness 写费用插件:把「这次会话花了多少钱」算准
前端·deepseek
星光不问赶路人12 小时前
Vue 3 + TypeScript 中 enum 的使用实践
前端·vue.js
鸥梨菌Honevid12 小时前
UVM 中 REQ 和 RSP 类型详解:从通信模型到 item_done 与 put_response
java·前端·servlet