text-size-adjust: 100% 是唯一能从 CSS 层面干预系统字体放大的有效属性,但必须写在 html 或 body 上且不能用 none 值;iOS Safari 对小于 16px 文本强制放大,不走 CSS 继承链;Android WebView 和微信 X5 内核不支持该属性,需 JS 桥接修复。

text-size-adjust: 100% 是唯一能从 CSS 层面干预系统字体放大的有效属性,但它必须写在 html 或 body 上才生效,且不能用 none 值。
为什么只给 input 或 p 加 -webkit-text-size-adjust 没用
iOS Safari 对小于 16px 的文本强制放大,这个行为发生在渲染底层,不走 CSS 继承链。哪怕你给 input 单独写了 -webkit-text-size-adjust: 100%,只要它最终计算出的 font-size 小于 16px(比如 1.2rem 在系统大字体下算出来是 14px),放大仍会发生。
常见错误现象包括:
- 开发者工具里看到
Computed的font-size是 14px,但样式表里明明写了16px - 用了
rem却没控制好根字号,导致换算后掉进临界值以下 - UI 库(如 Vant、Ant Design Mobile)的内联样式或高优先级 class 覆盖了你的规则
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 直接对表单控件批量声明:
input, textarea, select { font-size: 16px; -webkit-text-size-adjust: 100% !important; } - 必须用
px或clamp()这类能保证最终值 ≥16px 的写法,避免em/rem引入不确定性 - 加
!important—— Android 微信 X5 内核和部分 UI 库会忽略无权重的声明
Android WebView 里 -webkit-text-size-adjust 根本不认
Android 微信 X5 内核、部分厂商 WebView(如华为 EMUI)压根不解析 -webkit-text-size-adjust。你在控制台执行 getComputedStyle(document.body).webkitTextSizeAdjust 会返回空字符串,说明属性被跳过。
这不是写法问题,是内核不支持。此时必须靠 JS 桥接:
- 监听
WeixinJSBridgeReady,调用WeixinJSBridge.invoke('setFontSizeCallback', {fontSize: 0}) - 同时监听
menu:setfont事件,防止用户手动点菜单触发二次放大 - 这段 JS 必须放在
里尽早执行,不能等DOMContentLoaded—— 否则页面已错乱才修复,用户会看到闪动
注意:fontSize: 0 表示“用系统默认字号”,不是“最小字号”;某些 ROM 需 fallback 到检测 window.matchMedia('(min-resolution: 2dppx)') + 动态重设 html 的 font-size。
text-size-adjust 必须全局声明,且不能放在 @media 里
这个属性必须作为顶层 CSS 规则出现,写在任何 @media 查询内部都无效。浏览器在解析媒体查询前就已应用了字体缩放策略,此时再覆盖为时已晚。
推荐写法(兼容 iOS 16.4+ 和旧版):
html {
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
text-size-adjust: 100%;
}
关键细节:
- 不要写在
:root或html:has(*)这类伪类上,部分 Android WebView 不支持 - 不要用
none—— iOS 13+ 已废弃,桌面 Safari 会彻底禁用缩放功能 - 如果项目用了
rem,确保html { font-size: 100% }或未被 JS 覆盖,否则系统字体设置无法传导到底层
真正容易被忽略的是:哪怕你 JS 和 CSS 都配齐了,在 Android 厂商定制 ROM 或微信 X5 中,setTextZoom(100) 和 setFontSizeCallback 仍可能被绕过。这时候得检查是否漏了 touch-action: manipulation 防止手势干扰,以及是否所有固定宽容器(如 width: 750px)都已转成 max-width + width: 100% —— 否则横向滚动会触发 WebView 自身的缩放逻辑,让所有 CSS 补丁失效。


















