tabindex有三类值:-1不可Tab聚焦但可JS聚焦;0按DOM顺序加入Tab序列,最安全;n>0强制提前但破坏可访问性,不推荐。非交互元素加0危险,因无默认事件响应,需语义化替代或补全ARIA与键盘事件。

tabindex 属性值的含义和行为差异
tabindex 不是简单的“数字越大越先聚焦”,它的三个取值范围有完全不同的语义:
-
tabindex="-1":元素不能通过 Tab 键进入,但可通过 JavaScript 调用focus()主动聚焦(比如模态框打开后自动聚焦到关闭按钮) -
tabindex="0":元素按 DOM 顺序加入默认 Tab 序列,不改变原有流式布局顺序,是最常用、最安全的取值 -
tabindex="n"(n > 0):强制提前进入 Tab 序列,所有正数按数值升序排列,但会破坏可访问性——屏幕阅读器用户和键盘用户会感到跳转突兀,WCAG 明确不推荐
为什么给非交互元素加 tabindex="0" 很危险
给 <div> 或 <span> 加 tabindex="0" 后,它确实能被 Tab 到,但按下 Enter 或 Space 不会触发任何行为——它没有原生语义,也没有默认事件响应。用户聚焦后卡住,不知道该做什么。
- 正确做法:用语义化标签替代,比如把可点击的
<div onclick="...">改成<button type="button"> - 若必须用非表单元素(如自定义下拉),需手动添加
role(如role="button")、aria-pressed等,并监听keydown处理 Enter/Space - 浏览器不会为
tabindex="0"的<div>自动添加outline样式,容易导致键盘焦点“消失”,必须用 CSS 补全::focus { outline: 2px solid #007bff; }
Tab 键顺序实际由 DOM 顺序 + tabindex 共同决定
很多人以为设了 tabindex="1" 就一定第一个被聚焦,其实不然。浏览器先按 HTML 文档流收集所有 tabindex >= 0 的元素,再排序:
- 所有
tabindex="0"元素保持原始 DOM 顺序 - 所有
tabindex="1"、tabindex="2"… 按数值升序排在前面(但多个相同值时,仍按 DOM 顺序) - 没写
tabindex或tabindex="-1"的元素不参与序列
示例:<input tabindex="2"><button tabindex="0"><a tabindex="1"> 的实际 Tab 顺序是 <a> → <input> → <button>,不是按标签位置来。
立即学习“前端免费学习笔记(深入)”;
移动端和 Safari 的 tabindex 特殊表现
iOS Safari 默认禁用大部分非表单元素的 Tab 导航(即使写了 tabindex="0"),只对 <input>、<textarea>、<select>、<button> 和带 contenteditable 的元素生效。Android Chrome 相对宽松,但也不保证一致。
- 不要依赖
tabindex在移动端实现复杂导航逻辑 - 如果目标是让某个区域可滚动并支持键盘聚焦(如长列表),用
tabindex="0"+scrollIntoView()更可靠 - 检查是否启用了“辅助功能→键盘→全键盘控制”(macOS/iOS),否则 Safari 可能完全忽略 tabindex
真正难的不是设哪个数,而是想清楚:这个元素是否真的需要键盘可访问?它有没有明确的交互目的和反馈?如果答案模糊,先别加 tabindex。



















