必须iOS和Android双端分治:iOS用html{text-size-adjust:100%;-webkit-text-size-adjust:100%!important},Android必须JS桥接WeixinJSBridge.invoke('setFontSizeCallback',{fontSize:0}),漏一端即闪动错位。

不能只靠 CSS,iOS 和 Android 微信必须分两路处理:iOS 用 text-size-adjust 配合强制字号,Android 必须走 JS 桥接;漏掉任一端,页面横屏或点菜单时就会闪动错位。
为什么 text-size-adjust: 100% 在 iOS 微信里要写在 html 上且加 !important
iOS 微信基于 Safari WebKit,会读取 -webkit-text-size-adjust,但它的解析优先级低、易被覆盖。只写在 body 或某个 div 上完全无效——浏览器只检查文本最近的「根级容器」是否设了该属性。
-
html { text-size-adjust: 100%; -webkit-text-size-adjust: 100% !important; -moz-text-size-adjust: 100% !important; }是最稳妥写法 - 必须加
!important:微信内置样式、第三方 UI 库(如 Vant)常带内联或高权重规则,不加容易被干掉 - iOS 16+ 对前缀拦截更严,
text-size-adjust: 100%(无前缀)必须存在,不能只靠-webkit-版本 - 别用
* { text-size-adjust: 100% }:旧版 Safari 可能忽略通配符,且性能差
为什么 Android 微信里加了 -webkit-text-size-adjust 也没用
Android 微信用的是 X5 内核,它压根不解析 -webkit-text-size-adjust。你在控制台执行 getComputedStyle(document.body).webkitTextSizeAdjust,返回一定是空字符串 "",不是写法错,是内核不支持。
- CSS 层面对 X5 完全不可见:它改的是整个 WebView 的
setTextZoom,不是单个元素渲染逻辑 - 必须用 JS 桥接:
WeixinJSBridge.invoke('setFontSizeCallback', {fontSize: 0}),其中0表示“恢复系统默认”,不是“最小字号” - 这段 JS 要放在
里尽早执行,不能等DOMContentLoaded——否则页面已错乱再修,用户会看到明显闪动 - 还要监听
menu:setfont事件,防止用户手动点微信菜单里的“调整字体”再次触发
表单控件(input/textarea)为啥单独处理
iOS Safari 对表单元素有额外干预逻辑:只要最终计算出的 font-size < 16px,哪怕写了 -webkit-text-size-adjust: 100%,它也会强行放大整个输入框区域,导致高度突变、placeholder 错位。
- 必须显式设置
font-size: 16px(或等效绝对值,如clamp(16px, 4vw, 18px)),避免用rem或em引入精度误差 - 推荐直接作用于控件:
input, textarea, select { font-size: 16px !important; -webkit-text-size-adjust: 100% !important; } - 如果用了 rem 基准,确保根
html的font-size× rem 值 ≥ 16px,且不要设成 12px 这类临界值
可访问性不能牺牲,text-size-adjust: none 是条死路
none 会彻底禁用系统级“增大文字”设置,低视力用户无法缩放,MDN 明确标注生产环境应避免。真实项目里最顽固的问题不是技术实现,而是「谁先渲染、谁后接管」:
- iOS Safari 在 CSS 解析前就做了渲染层干预
- X5 内核则在 JS 执行后才覆盖字号基准
- 这两套机制互不兼容,必须分层应对:CSS + JS + 表单加固,三者缺一不可
- 最容易被忽略的是动态插入的内容(比如弹窗、懒加载模块),它们可能没继承到根级
text-size-adjust,得额外兜底
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











