当前位置: 首页 > news >正文

基于 Flexible.js + postcss-px-to-viewport 的 REM 适配方案(支持系统缩放与浏览器缩放)

上一篇文章的进化版本

背景

在响应式布局开发中,px 单位逐渐被 remvw 替代,前者配合 flexible.js 适配不同设备的屏幕宽度,后者则直接依赖视口宽度。我们选择使用 rem 单位,是因为它具备更高的控制精度,且便于与字体缩放逻辑结合使用。同时,为了兼容系统级缩放(如 Windows 125%、150%)和浏览器缩放(Ctrl + / Ctrl -),我们对 flexible.js 进行了一次魔改,使其在设置根字体大小时,自动感知系统与浏览器缩放因子,从而保持页面在各种缩放设置下的视觉一致性。


核心思路

本方案由三部分组成:

  1. 使用 postcss-px-to-viewport 插件将 px 自动转为 rem 单位
  2. 魔改 flexible.js,动态设置根节点的 font-size,感知系统与浏览器缩放
  3. 通过 zoom.ts 模块获取缩放信息,辅助计算准确的 rem

1. 配置 postcss-px-to-viewport

我们将所有 px 转换为 rem,并将视口宽度配置为设计稿宽度(如 1920px)。这是 flexible.js 动态设置 rem 的基础。

// vite.config.ts
import postcsspxtoviewport from 'postcss-px-to-viewport';postcsspxtoviewport({unitToConvert: 'px',viewportWidth: 1920,unitPrecision: 5,propList: ['*'],viewportUnit: 'rem',fontViewportUnit: 'rem',selectorBlackList: [],minPixelValue: 1,mediaQuery: false,replace: true,exclude: undefined,include: undefined,landscape: false,landscapeUnit: 'rem',landscapeWidth: 1920,
});
  • 注意:此处 viewportUnitfontViewportUnit 都设置为 rem,不是默认的 vw
  • 我们依赖 flexible.js 来动态控制 rem 与实际像素之间的比例。

2. 魔改 flexible.js:动态计算 rem

function refreshRem() {const { systemZoom, browserZoom } = getAllZoom();let width = document.documentElement.getBoundingClientRect().width;if (width / dpr > 540) {width = width * dpr;}let ratio = 100;if (systemZoom === 1) {ratio = 100;} else if (systemZoom > 1 && systemZoom <= 1.25) {ratio = 100 / systemZoom;} else if (systemZoom >= 1.5) {ratio = 120 / systemZoom;}let rem = width / ratio;rem = rem * browserZoom;document.documentElement.style.fontSize = rem + 'px';window.rem = rem;
}

调整逻辑说明:

  • systemZoom:主要用于补偿系统设置导致的页面拉伸,比如 Windows 设置了 125%、150% 缩放。
  • browserZoom:确保用户主动浏览器放大(Ctrl +)时页面字体/布局也能自然放大。
  • 最终的 rem:= viewportWidth / ratio × browserZoom

3. 获取缩放信息:zoom.ts 模块

function getZoom() {if (window.devicePixelRatio !== undefined) {return getDecimal(window.devicePixelRatio);}if (window.outerWidth && window.innerWidth) {return getDecimal(window.outerWidth / window.innerWidth);}return 1;
}function getAllZoom() {const zoom = getZoom();const browserZoom = getDecimal(window.outerWidth / (window.innerWidth || 1));const systemZoom = getDecimal(zoom / browserZoom);return {zoom,browserZoom,systemZoom,systemResolution: Math.round(window.screen.width * systemZoom),};
}
  • devicePixelRatio:总缩放倍数(系统 × 浏览器)
  • outerWidth / innerWidth:用于反推出浏览器缩放倍数
  • zoom / browserZoom:反推出系统缩放倍数

最终效果

  • 页面布局单位使用 rem,支持动态字体缩放;
  • 在系统级缩放(例如 Windows 150% 缩放)下页面保持正常比例;
  • 用户 Ctrl + 放大页面时,布局和文字也能随着放大;
  • 同时兼容高分屏和低分屏,兼顾开发体验和视觉一致性。

优势总结

方案是否兼容系统缩放是否兼容浏览器缩放开发难度控制粒度
使用 vw❌ 视觉比例会偏差差(字体不易控)
使用原生 rem简单一般
本方案(rem + zoom)高(字体、布局都受控)

注意事项

  • 本方案在 Chrome、Edge 等现代浏览器下验证良好;
  • 不适用于需要支持 < IE11 的场景;
  • 若使用 devtools 或双屏环境调试,缩放倍率检测可能受影响;
  • 可结合 Tailwind CSS 或 PostCSS 构建体系使用。

结语

在多端适配越来越复杂的今天,仅依赖一种单位(如 vw 或 px)已经无法保证体验一致性。借助 rem + flexible.js + 浏览器缩放检测,我们构建了一个兼容性强、体验优秀的视觉适配方案,值得在中大型系统中推广应用。

如果你正在为视觉缩放一致性烦恼,不妨试试这个方案!

http://www.lryc.cn/news/605175.html

相关文章:

  • SpringBoot+Three.js打造3D看房系统
  • ts 基础知识总结
  • 深入理解PostgreSQL的MVCC机制
  • 【自动化运维神器Ansible】Ansible常用模块之group模块详解
  • C++反射
  • 中大网校社会工作师培训创新发展,多维度赋能行业人才培养
  • vue+elementui+vueCropper裁剪上传图片背景颜色为黑色解决方案
  • OriGene:一种可自进化的虚拟疾病生物学家,实现治疗靶点发现自动化
  • Java 笔记 封装(Encapsulation)
  • vulhub-Thales靶场攻略
  • LRU (Least Recently Used) 缓存实现及原理讲解
  • Python读取获取波形图波谷/波峰
  • PSO-TCN-BiLSTM-MATT粒子群优化算法优化时间卷积神经网络-双向长短期记忆神经网络融合多头注意力机制多特征分类预测/故障诊断Matlab实现
  • Undo、Redo、Binlog的相爱相杀
  • 2025年华为HCIA-AI认证是否值得考?还是直接冲击HCIP?
  • 鸿蒙(HarmonyOS)模拟(Mock)数据技术
  • NestJS CLI入门
  • HPCtoolkit的下载使用
  • 7.Origin2021如何绘制拟合数据图?
  • 网络安全学习第16集(cdn知识点)
  • python 中 `batch.iloc[i]` 是什么:integer location
  • 【MySQL 数据库】MySQL索引特性(一)磁盘存储定位扇区InnoDB页
  • NEG指令说明
  • Android补全计划 TextView设置文字不同字体和颜色
  • 全视通智慧护理巡视:做护理人员的AI助手
  • 关于vue __VUE_HMR_RUNTIME__ is not defined报错处理
  • plex客户端升级以后显示的内容太多了怎么办?
  • 比特币挖矿的能源消耗和环保问题
  • 【图像处理】直方图均衡化c++实现
  • 个人如何做股指期货?