autofocus仅在HTML初始解析时对首个符合条件的原生表单控件生效,非“写上就聚焦”;动态插入、隐藏、disabled、多实例、移动端及SPA场景均失效,须用JS手动focus()并确保元素可见、已挂载且处于用户交互上下文。

autofocus 属性不是“写上就聚焦”的开关,它只在 HTML 初始解析阶段对第一个符合条件的原生表单控件生效;绝大多数失效场景,是因为浏览器压根没执行它——不是你代码错,是它没机会运行。
autofocus 什么时候根本不会触发
浏览器只在解析原始 HTML 字符串时扫描一次 autofocus,之后所有 DOM 变更都与它无关:
-
document.body.innerHTML = '<input type="text" autofocus>'→ 新增节点不重新解析,属性存在但无效 - Vue/React 组件里写
<input autofocus />→ SSR 或 hydration 后 DOM 才挂载,错过解析时机 -
<div style="display: none"><input autofocus></div>→ 元素初始不可见,被跳过 - 多个
<input autofocus>→ 只有源码中第一个被解析到的生效,其余静默忽略(HTML5 规范行为) -
<input type="hidden" autofocus>或<div autofocus>→ 元素本身不可聚焦,属性无效且不报错
哪些元素真正支持 autofocus
仅限原生、可交互、未禁用的表单控件,且浏览器支持该类型本身:
- ✅ 稳定支持:
<input type="text">、<input type="search">、<input type="email">、<textarea>、<button> - ⚠️ 条件支持:
<select>(Chrome/Edge 支持,Firefox 和旧 Safari 忽略);<input type="color">(属性可读写,但 Safari 不支持该类型) - ❌ 完全无效:
<input type="hidden">、<input disabled>、<input tabindex="-1">、<div tabindex="0">(autofocus不认tabindex)
移动端和 SPA 场景下必须用 JS focus()
iOS Safari 几乎总是静默丢弃 autofocus,SPA 路由切换后新渲染的输入框也一样。可靠做法是等 DOM 真实挂载、元素可见、且未被用户主动操作后再调用 .focus():
- React:用
useEffect(() => { inputRef.current?.focus() }, []),并包裹if (typeof window !== 'undefined')防 SSR 报错 - Vue 3:在
onMounted中调用inputRef.value?.focus(),确保v-if已为true - 原生 JS:监听
DOMContentLoaded后检查document.activeElement !== input,避免覆盖用户当前焦点 - 更稳妥的 iOS 方案:绑定一次
click或touchstart到按钮或body,回调中立即调用input.focus()
容易被忽略的焦点抢占问题
autofocus 不触发 focus 事件,也不保证软键盘弹出。更隐蔽的问题是:密码管理器、翻译插件、甚至某些框架内部逻辑,可能在页面加载后几毫秒内把焦点抢走。此时控制台无报错,autofocus 也确实执行过了,但光标就是不出现——这种“无声失效”,比语法错误更难定位。

















