Safari 的可访问性逻辑导致 input:focus 时页面放大,其硬编码检查聚焦元素的 font-size 计算值。

input:focus 时页面放大,根本不是缩放 bug,是 Safari 的可访问性逻辑
iOS Safari 在 input、textarea、select 或带 contenteditable 的元素聚焦时,会硬编码检查其最终渲染的 font-size。只要计算值
常见掉坑点:
-
html { font-size: 12px }+input { font-size: 1.333rem }→ 实际算出来 15.996px,Safari 四舍五入判为 - 父容器用了
font-size: 0.875em,子input继承后直接掉到 14px - 用了
clamp(14px, 4vw, 16px),小屏下 4vw 在 320px 宽度上仅 12.8px - UI 库(如
<van-field>)把font-size写进内联 style,你的 CSS 被覆盖
必须同时生效的三要素:viewport + 字号 + 选择器范围
缺一不可,且顺序和写法都有讲究:
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">必须放在<head>最顶部,不能 JS 动态注入 -
input、textarea、select、[contenteditable]都要显式设font-size: 16px !important,不能只写input - 必须加
:focus伪类规则,否则某些框架在 focus 时动态加 class 可能导致字号回落
推荐写法:
立即学习“前端免费学习笔记(深入)”;
input, textarea, select, [contenteditable] {
font-size: 16px !important;
}
input:focus, textarea:focus, select:focus, [contenteditable]:focus {
font-size: 16px !important;
}
-webkit-text-size-adjust: 100% 不是“一设就灵”,必须配合字号生效
这个属性只负责阻止 Safari 对文本的内部字号重计算,不干预视口缩放逻辑。如果 input 的最终渲染 font-size 小于 16px,哪怕加了 -webkit-text-size-adjust: 100%,iOS 仍会放大页面。
- 必须和
font-size ≥ 16px配合使用,它只在字号达标的前提下封堵二次干预 - 不能写在
body上——会导致正文小字也变难读;必须同级写在表单元素上 - 用
100%最稳妥,none在 iOS 10+ 已废弃,部分版本反而失效
正确写法:
input, textarea, select, [contenteditable] {
font-size: 16px !important;
-webkit-text-size-adjust: 100%;
}
Vue/React 项目里,CSS 很可能没生效
框架组件常在 mounted 阶段动态注入样式,或用 CSS-in-JS 生成高优先级 class,把你写的规则盖掉:
-
<van-field>或<Input>组件内部用内联 style 设置了font-size,得用更强选择器覆盖,例如:input:not([type="hidden"]) !important - 直接在组件上加
style="font-size: 16px !important"是最快验证方式 - 查「Computed」面板确认最终
font-size值,别信源码里写的那行 CSS - 避免用
rem/em,优先用px或clamp(16px, 4vw, 18px)(确保下限真 ≥16px)
Android 和其他浏览器不用刻意适配,这个行为是 iOS Safari 独有。但要注意:vh 单位在 iOS Safari 中不稳定(地址栏收放导致)。
真正容易被忽略的是:你写的 CSS 规则是否真被应用到了最终渲染节点上,而不是被框架、插件或内联样式悄悄覆盖。查 Computed,看真实值,比反复改代码更省时间。


















