postcss-pxtorem的rootValue必须与JS动态设置的根字体大小严格一致:375px设计稿对应37.5,750px设计稿对应75;混用px2rem-loader会导致重复转换;propList慎用['*'],避免1px边框失真;mediaQuery开启需谨慎,老Safari和Shadow DOM需class切换+fallback兜底。

CSS适配方案必须在构建时固化,不能靠运行时 JS 动态改根字体或媒体查询变量来“兜底”——否则真机上会漏掉关键断点、Safari 15.4 以下不生效、Shadow DOM 内失效、JS 修改后媒体查询不重触发。
postcss-pxtorem 的 rootValue 怎么设才不翻车
很多人直接写 rootValue: 75,结果 iPhone 12 上文字小得看不清,安卓低端机又撑满屏幕。根本原因是:75 是按设计稿宽度(比如 750px)÷10 得来的,但实际设备物理像素和逻辑像素不一致,dpr 会干扰 rem 计算。
- 推荐设为
rootValue: 37.5(对应 375px 设计稿),再配合mediaQuery: true开启媒体查询自动注入,让插件在不同断点下生成不同font-size - 若用 750px 设计稿,
rootValue必须是75,但得同步在 JS 入口里手动 setRemUnit,并确保它比 postcss-pxtorem 的 CSS 注入更早执行,否则样式先渲染、JS 后生效,闪屏 -
propList: ['*']要慎用——它会把border: 1px solid #000也转成border: 0.013rem,导致 1px 边框在 dpr=2+ 设备上变虚线;应改为['font', 'font-size', 'line-height', 'letter-spacing']
为什么 px2rem-loader 和 postcss-pxtorem 别混用
两者都干“px → rem”这事,但机制完全不同:px2rem-loader 是在 CSS 解析阶段做字符串替换,postcss-pxtorem 是在 PostCSS AST 层操作。混用会导致重复转换、单位错乱,比如 16px 变成 0.213rem 后又被转成 0.0028rem。
- Webpack 项目只选一个:
postcss-pxtorem更主流、支持mediaQuery、能配合 autoprefixer -
px2rem-loader仅适用于老项目迁移,或需要极简配置(不引入 PostCSS 生态)的场景 - 若用了
lib-flexible,必须禁用postcss-pxtorem的mediaQuery,否则 JS 设置的font-size和媒体查询生成的冲突,iOS 上表现不稳定
如何让 rem 方案兼容 Safari 15.4 以下 + Shadow DOM
Safari 15.4 才真正支持 @media (max-width) 内修改 :root 变量;老 Safari 和 Shadow DOM 内部,:root 声明根本不可见。
立即学习“前端免费学习笔记(深入)”;
- 对老 Safari:改用 class 切换方案,比如
html[data-dpr="2"] { font-size: 37.5px; },由 JS 检测window.devicePixelRatio后加 class - 对 Shadow DOM:不能依赖全局
:root,需在组件内显式声明,例如.card-host { font-size: var(--base-font-size, 16px); },再用 JS 注入 fallback 值 - 所有 rem 值必须带 fallback,如
font-size: calc(var(--font-md, 16px) / 16 * 1rem),避免变量未定义时样式崩塌
真正难的不是怎么写配置,而是搞清哪些逻辑该交给构建时(PostCSS)、哪些必须留给运行时(JS 检测 dpr)、哪些要手动兜底(class 切换、fallback 单位)。一旦混淆这三层,适配就变成玄学调试。


















