移动端文字忽大忽小是浏览器可访问性策略主动放大文本所致;text-size-adjust: 100% 是唯一稳定禁用方案,必须写在 body 上且不能用 none。

移动端文字大小“失控”不是 CSS 写错了,而是浏览器在渲染层主动干预的结果;text-size-adjust: 100% 是唯一稳定禁用该行为的 CSS 方案,但必须写在 body 上,且不能用 none。
为什么 font-size 声明值没变,但真机上文字忽大忽小?
这是浏览器的可访问性策略在起作用:Android Chrome 和 iOS Safari 都会检测文本块的上下文(如行宽、行高、父容器尺寸),当判定“当前字号过小、影响阅读”时,就绕过 CSS 计算,直接放大渲染后的文本行盒——你看到的错位、按钮被撑开、Grid 轨道崩塌,都是这个放大动作导致的布局重排。
常见错误现象:
- DevTools 模拟器里一切正常,真机上
font-size: 14px的菜单文字比正文小一圈 - 同一份
font-size: 1rem在header和footer中渲染大小不一致 - 聚焦
input[type="number"]后,整个页面文字突然变大,布局错乱
text-size-adjust: 100% 必须写在 body 上才生效
text-size-adjust 不走 CSS 继承链,也不响应选择器优先级。它只在 body 元素上注册时,才能覆盖浏览器默认的文本放大策略。写在 html、:root 或某个 div 上都无效。
立即学习“前端免费学习笔记(深入)”;
实操建议:
- 全局加这段 CSS,且确保它在首屏 HTML 中内联或早于 JS 加载:
body { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; text-size-adjust: 100%; } - 别用
none:iOS 13+ 已废弃,部分 Android WebView 会直接忽略,甚至破坏系统字体设置 - 不要依赖
!important:这个属性本身不参与优先级计算,加了也无用
数字输入框触发的放大必须单独加固
当用户聚焦 input[type="number"]、input[inputmode="numeric"] 或 input[type="tel"] 时,Android 厂商 WebView(如华为、小米)和旧版 iOS Safari 会偷偷调高 initial-scale 或强制放大文本——这和 text-size-adjust 是两套机制,必须双管齐下。
关键点:
-
font-size必须是固定值(如16px),不能是rem或em,否则 UA 可能二次缩放 - 必须同时声明
-webkit-text-size-adjust: 100%和text-size-adjust: 100%,部分旧 WebView 只认前者 - 微信安卓版需内联
!important才能生效:input[type="number"] { font-size: 16px !important; -webkit-text-size-adjust: 100% !important; text-size-adjust: 100% !important; }
viewport 配置和 text-size-adjust 是两回事,别混用
user-scalable=no 控制的是双指手势缩放,text-size-adjust 控制的是文本自动放大,二者完全独立。你可能同时遇到两种问题,但解决方案不能互相替代。
容易踩的坑:
- 以为加了
<meta name="viewport" content="..., user-scalable=no">就能防文字放大——完全无效 - 删掉
maximum-scale=1.0后发现数字键盘弹起更易缩放——其实是漏掉了font-size: 16px+text-size-adjust组合 - 在
@media查询里动态改text-size-adjust——该属性不响应媒体查询,只在初始渲染时读取一次
真正难处理的,是那些既需要小字号视觉效果(比如标注、图标旁说明),又得扛住所有 UA 干预的场景——这时候就得放弃 font-size,改用 transform: scale() 或 SVG 内嵌文本,而不是硬刚渲染层规则。


















