autofocus 属性在多数场景下直接失效,因其仅在HTML解析时对首个符合条件元素生效,动态插入、框架挂载、隐藏态模态框及SPA路由切换后均不触发;支持元素限于未禁用且可见的text/email/textarea/button,select兼容性差,hidden/checkbox/file/div[tabindex]等完全无效;iOS Safari因安全策略禁止非用户手势上下文自动唤起键盘,故首页或无手势调用focus()均失败;可靠方案是移除autofocus,用requestAnimationFrame延迟执行focus()并校验已挂载、可见、可聚焦三条件,且用户手势内同步调用。

autofocus 属性为什么在多数场景下直接失效
它只在浏览器解析原始 HTML 字符串时扫描一次,且仅对第一个满足条件的元素生效。动态插入(innerHTML、appendChild)、框架挂载(Vue v-if、React useState)、模态框隐藏态(display: none)、SPA 路由切换后新渲染的表单——这些场景中,autofocus 都是“过期状态”,浏览器压根不处理。
哪些元素真正支持 autofocus,哪些只是看起来支持
支持与否取决于类型 + 状态双重约束,不是写了就管用:
-
<input type="text">、<input type="email">、<textarea>、<button>:✅ 安全可用,只要未disabled、初始可见、无inert父级 -
<select>:⚠️ Chrome/Edge 可能聚焦,Firefox 和旧 Safari 会静默忽略,控制台报错autofocus is not supported on <select> -
<input type="hidden">、<input type="checkbox">、<input type="file">、<div tabindex="0">:❌ 完全无效,规范不支持
iOS Safari 下 autofocus 几乎必然失败的原因
iOS Safari 主动禁止非用户手势上下文中的自动键盘弹出。autofocus 属于页面加载行为,没有用户点击、触摸等触发源,因此被策略性跳过——这不是 bug,是设计如此。
- 首页写
<input autofocus>→ 光标不动,键盘不弹 - 模态框
show()后调input.focus(),若不在click或touchstart回调里 → 依然失败 - 哪怕聚焦成功,软键盘可能遮挡输入框,尤其在
position: fixed或 viewport 缩放后
真正可靠的兼容方案:focus() + 三重校验
删掉所有 autofocus 属性,统一用 JS 控制。但不能裸调 focus(),必须确保三个条件同时成立:
立即学习“前端免费学习笔记(深入)”;
- 已挂载:
input.isConnected为true,或input.offsetParent !== null - 可见:
getComputedStyle(input).display !== 'none'且visibility !== 'hidden' - 可聚焦:
input.tabIndex >= 0,且未disabled、未被inert阻断
推荐延迟一帧执行:requestAnimationFrame(() => input.focus()),避开 CSS transition 未完成或渲染未就绪的时机。若涉及用户手势(如点击按钮打开弹窗),务必把 focus() 放在该事件回调内同步执行,否则 iOS Safari 会拒绝。
真正麻烦的从来不是让输入框获得焦点,而是确保它聚焦后不会被其他逻辑覆盖、不会逃逸到弹窗外、不会破坏屏幕阅读器的焦点流——这些细节不校验,上线后第一轮无障碍测试就会卡住。



















