tabindex数字硬排顺序不可取,应依靠HTML源码位置控制焦点流;仅对非原生可聚焦但需键盘操作的容器用tabindex="0"并配role;tabindex="-1"仅用于JS主动聚焦且需DOM中预置。

别用 tabindex 数字硬排顺序——它不是 CSS z-index,加了 tabindex="1" 不会让按钮“跳到第一个”,只会把所有正数项塞到 Tab 流最前面,然后按 DOM 顺序乱跳。
哪些元素该加 tabindex="0"?
只加在本不可聚焦、但业务上必须支持键盘操作的容器上,比如:<div role="button">、<h3 role="tab">、自定义折叠面板标题。原生可聚焦元素(button、a[href]、input、select、textarea)默认就进 Tab 流,加了反而可能干扰 React 焦点管理或 SSR hydration。
- 必须同步加
role属性,否则屏幕阅读器读作“div”而非“按钮” - 必须监听
keydown,对Enter和Space做响应;Space要调e.preventDefault(),否则页面滚动 - CSS 若移除了
outline,得补:focus-visible { outline: 2px solid #007bff; },否则键盘用户看不见焦点在哪 - 避免给纯展示项(如头像
div、图标span、静态文本容器)加tabindex="0",这会增加无意义的焦点停顿
tabindex="-1" 的唯一合法用途是什么?
不是“隐藏”或“禁用”,而是让一个具体可交互元素不被 Tab 键碰到,但允许 JS 主动 .focus()。典型场景:模态框打开后聚焦第一个按钮、选项卡切换后聚焦内容区首项、侧边栏展开后聚焦首个 input。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 目标元素(如弹层内第一个
button)必须在 HTML 中就带tabindex="-1",不能等 JS 渲染完再动态设置——否则.focus()静默失败 - 不要给整个容器(如
role="dialog"根节点或role="tabpanel")设tabindex="-1",否则.focus()落在空容器上,用户按 Tab 仍会逃逸 - 确保 DOM 已渲染完成再调
.focus(),可用requestAnimationFrame或setTimeout(() => el.focus(), 0) - 聚焦后若元素被
overflow: hidden或transform遮挡,必须手动补el.scrollIntoView({ block: 'nearest' })
为什么永远不该写 tabindex="1"?
它不会让你控制“视觉第一”,只会制造焦点错乱。浏览器把所有正整数项提到整个 Tab 流最前面,再按数值升序排;同值时回退到 DOM 顺序——而你的 DOM 顺序很可能和视觉布局不一致。
立即学习“前端免费学习笔记(深入)”;
- 多个
tabindex="1"元素中,浏览器只认第一个,其余无效 - React/Vue 动态插入新组件后,硬编码的正数无法重算,焦点跳转错乱
- 移动端 Safari 直接无视大部分正数
tabindex,还可能触发控制台警告 - 屏幕阅读器把第一个
tabindex="1"当作逻辑起点,哪怕它是页脚的“导出”按钮 - 真正要控制顺序,靠的是 HTML 源码位置:导航栏放顶部,它就第一个被 Tab 到
最容易被忽略的一点:焦点接管不是设个 tabindex 就完事。你得确认元素已渲染、未被隐藏、有语义、有交互响应、有视觉反馈——少一环,键盘用户就卡住。


















