tabindex是键盘导航的核心控制属性,非装饰性;原生表单控件默认可聚焦,div等需设tabindex="0"才加入tab流;label绑定提升可访问性;keydown中慎用preventdefault避免阻断导航;移动端需手动管理焦点与滚动。

tabindex 是控制键盘导航的开关,不是装饰属性
表单能被 Tab 键顺序访问,靠的是浏览器对可聚焦元素的默认行为,不是“自动识别表单”——input、button、select、textarea 这些原生控件默认 tabindex="0";但 div、span、自定义组件默认不可聚焦,加了 tabindex="0" 才能进 Tab 流程。
常见错误现象:div 包裹的模拟下拉菜单按 Tab 跳过了,或者用 tabindex="-1" 误关掉了本该可聚焦的控件。
-
tabindex="0":加入默认 Tab 顺序,位置由 DOM 顺序决定 -
tabindex="-1":只能通过脚本.focus()聚焦,不能用 Tab 进入(适合弹窗关闭后手动聚焦回触发按钮) -
tabindex="1"及正数:强制插入 Tab 顺序,容易打乱逻辑流,绝大多数情况不该用 - 禁用状态的
input[disabled]自动退出 Tab 流程,比写tabindex="-1"更可靠
label 和 for 属性不只为了点击,它绑定键盘焦点
没写 label 或 for 不影响视觉,但会导致屏幕阅读器无法关联控件,且部分浏览器(如旧版 Safari)在按 Tab 到 input 后,再按 Enter/Space 无法触发关联的 label 内的 checkbox 或 radio。
使用场景:所有带文字说明的表单控件都该有语义化 label,尤其 checkbox 和 radio 组。
立即学习“前端免费学习笔记(深入)”;
- 推荐写法:
<label><input type="checkbox"> 接收邮件</label>(隐式绑定,无需for) - 显式绑定需确保
for值与input的id完全一致,大小写敏感 - 不要用
div+onclick模拟label,它不响应键盘空格/回车
阻止默认行为会直接切断键盘导航链
监听 keydown 时调用 e.preventDefault(),可能意外拦截 Tab、Shift+Tab、Enter 等关键导航行为。比如在 input 上做输入限制,却把 Tab 键也拦了,用户就卡死在当前字段。
性能影响不大,但体验断层明显:键盘用户无法离开这个框,又看不到报错提示,以为页面卡了。
- 只对目标键调用
preventDefault(),例如过滤非数字字符时,先判断e.key !== 'Tab' && e.key !== 'Enter' && e.key !== 'Escape' - 用
input事件替代keydown做值校验,它不干涉焦点移动 - 如果必须拦截 Tab(比如模态框内循环聚焦),要手动管理焦点,用
document.activeElement+.focus()接续流程
移动端软键盘唤起和焦点切换常被忽略兼容性
iOS Safari 对 autofocus 支持极差,且页面加载后立即 .focus() 很可能无效;Android Chrome 则可能在软键盘弹出后,把焦点元素滚出视口顶部,导致看不见输入框。
容易踩的坑:开发时只在桌面测 Tab 流程,上线后发现 iOS 用户点开页面根本没法输——因为第一个 input 没获得焦点,又没提供明确点击入口。
- 避免依赖
autofocus,改用用户手势触发后调用.focus()(如按钮点击、选项卡切换) - 唤起软键盘后,用
scrollIntoView({ block: 'nearest' })确保输入框可见 - 测试真机:iOS 上连按两次 Tab 键实际会跳到地址栏,不是页面内下一个元素
tabindex 就完事,它是一条从 DOM 结构、事件处理到移动端渲染的完整链路,任一环节断掉,用户就卡在那儿。











