autofocus仅在页面首次加载时对首个可见、可聚焦且未禁用的原生控件生效,动态插入、框架hydration、隐藏状态、ios safari及disabled/inert等均导致失效;focus()失败主因是时机不当或元素状态不满足。

autofocus 属性在绝大多数真实场景中不可靠,别指望它“写上就聚焦”——它只在 HTML 初始解析时对第一个可见、可聚焦、未禁用的原生控件起一次作用,之后全失效。
autofocus 为什么写了却没反应
不是代码写错了,是浏览器压根没执行它。常见失效原因包括:
-
autofocus只在页面首次加载时扫描原始 HTML 字符串,动态插入(如innerHTML = '<input autofocus>')完全不触发 - Vue/React 模板里写
<input autofocus>→ hydration 完成后 DOM 已存在,错过解析时机 - 模态框初始
display: none,JS 切成block后再显示 → 解析时不可见,直接跳过 - iOS Safari 几乎总是静默忽略,这是策略限制,防止非用户手势触发键盘弹出
- 元素被
disabled、tabindex="-1"、父级有inert,或包裹在visibility: hidden容器中 → 不参与聚焦流程
哪些元素真正支持 autofocus
支持与否取决于状态比类型更关键,必须同时满足:原生可聚焦 + 未 disabled + 初始可见 + 无 inert 父级。
- ✅ 安全可用:
<input type="text">、<input type="email">、<textarea></textarea>、<button></button> - ⚠️ 条件可用:
<select></select>(Chrome/Edge 支持,Firefox 和旧 Safari 忽略,错误信息:autofocus is not supported on <select></select>) - ❌ 完全无效:
<input type="hidden">、<input disabled>、<div autofocus>、<code><input style="display:none">focus() 方法调用失败的典型原因
手动调用
.focus()看似可控,但失败往往是因为时机或状态不对:- 脚本放在
里直接执行 →document.querySelector('input')返回null - Vue 的
onBeforeMount或 React 的useEffect空依赖数组里调用 → 框架尚未完成挂载,ref还是null - 聚焦前元素不在视口内,且未配合
.scrollIntoView({ block: 'nearest' })→ 聚焦成功但被遮挡,尤其在position: fixed区域 - 移动端非用户手势上下文调用(比如 Ajax 回调后立刻
input.focus())→ 键盘不弹出,光标也不亮 - 多个
.focus()调用竞争,或和autofocus混用 → 后者可能先触发又立刻被 JS 覆盖,行为不可预测
真正可靠的聚焦时机与写法
关键不是“怎么写”,而是“什么时候写”和“写之前确认什么”:
- 原生 JS:监听
DOMContentLoaded,再检查document.activeElement !== input,避免覆盖用户当前输入 - React:
useEffect(() => { ref.current?.focus() }, []),加if (typeof window !== 'undefined')防 SSR 报错 - Vue 3:
onMounted(() => inputRef.value?.focus()),确保v-if已为true - 移动端兜底:绑定一次
click或touchstart到body,回调中立即input.focus() - 表单重置后:监听
form.reset事件,用setTimeout(() => input.focus(), 0)恢复焦点
- 脚本放在











