tabindex是可访问性底层开关,非装饰属性;默认可聚焦元素为(含href)、、、、等,其隐式tabindex相当于0;等容器默认不可聚焦,需显式设tabindex="0"才可进入tab流,设tabindex="-1"仅支持js编程聚焦,禁用正整数以避免导航断裂。

tabindex 不是用来“美化 tab 导航顺序”的装饰性属性,它是可访问性的底层开关——关了,键盘用户根本进不来;开了,但设错值,反而会破坏导航流。
哪些元素默认有 tabindex?为什么 <div> 按 Tab 键没反应
<p>只有少数语义化元素原生可聚焦:<code><a></a>(带 href)、<button></button>、<input>、<select></select>、<textarea></textarea> 等。它们的隐式 tabindex 相当于 0,无需显式声明。
<div>、<code><span></span>、<li> 这类容器默认不可聚焦,按 Tab 键自然跳过。这不是 bug,是规范行为。
- 想让
<div onclick="doSomething()"> 也响应键盘操作?必须加 <code>tabindex="0" - 只希望它能被 JS 聚焦(比如模态框打开后自动聚焦),但不参与 Tab 流?用
tabindex="-1" - 千万别写
tabindex="false"或tabindex=""—— 浏览器会当作0处理,造成意外可聚焦 - 屏幕阅读器用户可能在页面开头就遇到一个位于底部的按钮,上下文断裂
- 多个
tabindex="1"元素共存时,浏览器按源码顺序排序,而非声明顺序,极易误判 - 一旦混用
tabindex="1"和tabindex="2",后续维护者很难推断焦点路径,测试成本陡增 - 或者改用
<textarea readonly></textarea>替代(需隐藏边框和 resize 控制器) - 更稳妥的做法:避免让非语义容器承担滚动+焦点双重职责;优先用
<section aria-label="..."></section>+tabindex="0",滚动交由内部子元素处理
tabindex="0" 和 tabindex="1" 的实际差别远不止“谁先谁后”
tabindex="0" 表示“按文档顺序插入当前焦点流”,它不抢权,也不降级,是最安全的可聚焦方式。
tabindex="1"(或任何正整数)会强制把该元素提到所有 tabindex="0" 元素之前——哪怕它在 DOM 里排在最后。这容易引发两个问题:
真实项目中,95% 的场景只需 tabindex="0" 或 tabindex="-1"。正整数 tabindex 是“手术刀级操作”,不是常规手段。
滚动容器 + tabindex:一个常被忽略的交互陷阱
给一个带 overflow-y: auto 的 <div> 加了 <code>tabindex="0",本意是让它可聚焦以便键盘导航,但你会发现:聚焦后按方向键无法滚动内容。
原因在于:可聚焦 ≠ 可滚动。浏览器只对原生可滚动元素(如 <textarea></textarea>、<iframe></iframe>)默认启用方向键滚动;对普通 <div tabindex="0">,方向键无响应。
<ul>
<li>解决办法是手动监听 <code>keydown,判断 ArrowUp/ArrowDown 并调用 element.scrollTop
最易被忽略的一点:tabindex 值超过 32767 会被截断为 32767;而 tabindex="-0" 会被解析为 0 —— 这些边界行为在自动化测试里几乎不会覆盖,却会在老旧系统或辅助技术中暴露问题。











