必须用document.documentElement.style.fontSize控制缩放,因其唯一兼顾全站rem自动响应、不干扰em计算、不覆盖系统级文本缩放;改body或逐个元素修改会引发嵌套放大、截断文字、热区错位等问题。

为什么必须用 document.documentElement.style.fontSize 控制缩放
改 html 元素的 font-size 是唯一能同时满足三点的做法:全站 rem 文字自动响应、不干扰 em 计算逻辑、不覆盖用户操作系统级文本缩放设置。Windows 的“放大文本”或 macOS 的“更大字体”会直接修改浏览器对 html 根字号的解析值,如果你用 body { font-size: 18px } 或逐个改 p.style.fontSize,系统缩放就被强制清零——视障用户可能看到文字被截断、按钮热区错位、行高撑破容器。
常见错误现象:
-
body上设font-size后,div { font-size: 1.2em }会先按系统缩放算一次,再按body值二次放大,结果不可控 - 用
transform: scale()缩放整个body,图片和布局一起变,但屏幕阅读器仍读原始尺寸,可访问性完全失效
rem 和 em 混用时哪些地方容易崩
rem 稳在“只认根”,em 活在“父说了算”。混用本身没问题,但失控点往往藏在细节里:
- 把
em用在容器宽高(如width: 20em)——父元素font-size一变,布局就漂移 - 在媒体查询里调
html { font-size: 18px },又在组件里写padding: 1em,结果 padding 被放大两次(根字号变 + em 继承) -
line-height: 1.6(无单位)是安全的,但写成line-height: 1.6em就等于1.6 × 父字号 × 父字号,嵌套深了直接失真
实操建议:标题、段落、卡片间距统一用 rem;按钮内边距、图标尺寸、行高优先用无单位数值或 em(前提是父级 font-size 稳定)。
立即学习“前端免费学习笔记(深入)”;
系统级文本缩放怎么测才真实有效
不能只靠浏览器缩放(Ctrl +),那只是渲染层缩放,骗不过可访问性树。必须在操作系统层面开真实文本缩放:
- Windows:设置 → 显示 → 缩放与布局 → “放大文本” 拉到 125% 或 150%
- macOS:系统设置 → 辅助功能 → 显示 → “文本大小” 拉到最大档
- 测试重点:文字是否等比变大、行高是否同步撑开、有没有文字被截断或溢出容器、第三方组件(如日期选择器、富文本编辑器)是否仍可操作
注意:px、vw、transform: scale() 在这种测试下完全没反应,只有 rem 和 em 会动——这正是你要验证的点。
动态调节按钮该传什么值给 html.style.fontSize
三档切换(小/中/大)推荐用百分比基准,而不是固定像素:
- 小号:
document.documentElement.style.fontSize = '87.5%'(≈14px,基于默认 16px) - 中号:
document.documentElement.style.fontSize = '100%'(保持系统默认) - 大号:
document.documentElement.style.fontSize = '125%'(≈20px)
这样做的好处是:不硬写死 14px,用户若已把浏览器默认字号设为 20px,你的“大号”就会变成 25px,真正尊重用户偏好。记得用 localStorage 存值,并在页面加载时立即应用,避免闪屏。别忘了监听 os-level text zoom 变化(通过 matchMedia('(prefers-reduced-motion)') 不行,得靠 resize + font-size 检测组合技,实际项目中常简化为 onload 后取一次 getComputedStyle(document.documentElement).fontSize 作 fallback)。
最易被忽略的一点:所有用 rem 的地方都依赖根字号,但 line-height、letter-spacing、border-radius 这些属性如果也用了 rem,它们会跟着一起放大——这未必是你想要的,得单独评估是否要锁死或换单位。



















