autofocus仅在html首次解析时对首个可见可聚焦的原生表单控件生效,不响应动态插入、css隐藏、多实例或spa路由切换;移动端及ios常静默忽略,需js手动focus()并注意时机与兼容性。

autofocus 属性只在页面首次 HTML 解析时生效,不是“写上就聚焦”的魔法开关。绝大多数“没反应”的情况,是因为浏览器压根没处理它——不是你代码错了,是它根本没机会运行。
autofocus 只对特定元素和状态有效
它只作用于原生可聚焦、可输入的表单控件,且要求元素初始可见、未被禁用:
-
<input type="text">、<input type="search">、<input type="email">、<textarea></textarea>✅ 稳定支持 -
<select></select>⚠️ Chrome/Edge 支持,Firefox 和旧版 Safari 可能忽略(错误信息:autofocus is not supported on <select></select>) -
<input type="hidden">、<input type="checkbox">、<input disabled>、<div autofocus> ❌ 静默失效,不报错 <li>元素包裹在 <code>display: none或visibility: hidden容器中 → 聚焦被跳过 - 父级有
inert属性或自身tabindex="-1"→ 不参与自动聚焦流程 - 源码顺序决定“第一个”,不是渲染顺序,也不是 JS 挂载顺序
-
document.body.innerHTML = '<input autofocus>'→ 新增 DOM 不触发重新解析,属性存在但无效果 - Vue/React 组件里写
<input autofocus>→ SSR 渲染或 hydration 后 DOM 已存在,错过解析时机 - 模态框初始
display: none,之后 JS 切换为block→ 解析时不可见,autofocus 被丢弃 -
form.reset()后不会恢复 autofocus,必须手动调用.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() - 别依赖
input.addEventListener('focus', handler)捕获 autofocus 行为 → 大概率收不到 - 若需监听,必须手动调用
el.focus(),它才会触发focus事件 -
.focus({ preventScroll: true })可防止页面滚动,autofocus没这个能力 - 移动端过早弹出键盘可能遮挡内容,尤其在模态框中,建议改用用户点击后再聚焦
多个 autofocus 元素或动态插入必然失效
HTML 规范明确:同一文档中,只有第一个被解析到的 autofocus 元素会生效,其余全部忽略。这不是 bug,是标准行为:
移动端和 SPA 场景下必须用 JS 手动 focus()
iOS Safari 几乎总是静默忽略 autofocus;SPA 路由切换后新渲染的输入框也不会自动聚焦。可靠做法是等 DOM 真实挂载、元素可见、且未被用户主动操作后再调用 .focus():
autofocus 不触发 focus 事件,也不保证键盘弹出
它只是让浏览器把焦点设过去,不派发 focus 事件(旧版 Safari 除外),更不会强制唤起软键盘:
真正容易被忽略的点是:autofocus 是一个一次性、声明式、与 DOM 解析强耦合的行为,它不响应后续任何变化。现代前端项目里,把它当兜底方案可以,但指望它在 SPA、模态框、iOS 上稳定工作,等于放弃控制权。











