必须用 document.documentElement.style.fontSize 动态改根字号,因改 body 或容器 font-size 会导致 em 二次放大、覆盖系统缩放、遗漏弹窗等外部元素;tab 切换仅作通知时机,统一调用 updateRootFontSize 更新根字号,并配合 rem/CSS 变量、清除 !important、替换 px、处理 iframe/shadow DOM 及强制 reflow。

必须用 document.documentElement.style.fontSize 动态改根字号,其他方式都会漏元素、破坏系统缩放或导致嵌套错乱。
为什么不能在 tab 切换时只改 body 或某个容器的 font-size
改 document.body.style.fontSize 会让所有 em 值二次放大(比如父 body 设为 18px,子元素 1.2em 就变成 21.6px),而用户系统缩放(Windows “放大文本”/macOS “更大字体”)会被覆盖——视障用户可能直接看不到完整文字。改某个 tab 容器的 style.fontSize 更危险:弹窗、悬浮提示、第三方组件(如日历、富文本)通常不在该容器内,它们的字号完全不受控。
tab 切换时怎么安全触发字体重算
核心是保持根字号唯一信源,tab 切换只是“通知时机”,不是“修改入口”。实际操作分三步:
- 页面加载时从
localStorage读取上次字号值(如"120%"),立即赋给document.documentElement.style.fontSize - 每个 tab 内容区不写死
px,全部用rem或 CSS 变量(如font-size: var(--font-scale, 1rem)) - tab 切换事件里不操作样式,只调用一个统一函数:
updateRootFontSize(currentScale),内部仍走document.documentElement.style.fontSize = currentScale + '%'
常见失效原因和快速定位法
不是 JS 没执行,而是样式层卡住了最终渲染:
立即学习“前端免费学习笔记(深入)”;
-
font-size被!important覆盖(尤其第三方组件的.dialog-title { font-size: 18px !important; })→ 打开开发者工具,看Computed面板里font-size的“来源”,点进去确认是否被更高优先级规则拦截 - 存在硬编码
px(如h1 { font-size: 32px; })→ 全局搜font-size:[^}]*px,替换成2rem或接入变量 - 某些 tab 用了 iframe 或 shadow DOM → 它们不继承根字号,需单独向其
document注入相同fontSize设置
最易被忽略的是:tab 切换后未触发 reflow,浏览器可能缓存了旧的 rem 计算结果。加一行 document.documentElement.offsetHeight 强制重排,能解决部分“切换后字号没变”的假象。



















