非表单元素需加tabindex="0"并配role属性、监听keydown处理enter/space、提供:focus-visible样式,缺一不可;禁用正整数tabindex,避免给静态元素添加无效焦点。

HTML本身不提供键盘可访问性,必须靠显式设置 tabindex、监听 keydown、补充 ARIA 语义并管理焦点流——缺一不可,否则键盘用户根本进不去、找不到、按不动。
怎么让非表单元素支持 Tab 焦点
默认只有 input、button、a 等原生可聚焦元素能被 Tab 进入。div、span、自定义卡片等必须手动加 tabindex="0" 才能进入焦点流。
-
tabindex="0"表示按 Tab 时可聚焦,且顺序跟随 DOM 位置;不要用tabindex="1"之类正数,它会打乱默认流 - 避免给静态文本或装饰性元素加
tabindex,屏幕阅读器会误读为可交互内容 - 移除禁用状态的元素时,同步设
aria-disabled="true"并移除tabindex,否则键盘用户仍能聚焦但无法操作
Enter 和 Space 键怎么统一响应
键盘用户习惯按 Enter 或 Space 触发点击,但 click 事件对键盘无效。必须监听 keydown 并手动拦截。
- 在按钮类元素上监听:
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleClick(); } - Space 键默认会滚动页面,所以
e.preventDefault()不可省略 - 别只监听
Enter:某些组件(如复选框模拟)需要 Space 切换状态,而 Enter 是确认提交 - 不要在
div上直接绑click——键盘用户永远触发不到
为什么键盘操作后焦点“消失”了
焦点没消失,是它跑到了不可见、不可聚焦或 DOM 已销毁的节点上。常见于模态框关闭、下拉收起、动态列表更新后。
- 模态框关闭后,必须把焦点手动切回触发按钮:
triggerButton.focus() - 动态渲染新列表项后,若想默认聚焦第一个,得等 DOM 更新完成再调
items[0]?.focus() - 用
document.activeElement检查当前焦点,比猜更可靠;配合console.log(e.target)在keydown里看实际是谁在响应 - 某些框架(如 React)会在 state 更新后重置焦点,需用
useEffect或ref主动恢复
:focus-visible 怎么写才不被忽略
没视觉反馈的键盘导航等于盲操。Chrome/Firefox 支持 :focus-visible,但必须配合正确 CSS 和 HTML 结构才能生效。
- CSS 必须显式声明:
button:focus-visible { outline: 2px solid #007aff; outline-offset: 2px; } - 不能只写
:focus,否则鼠标点击也会出轮廓,体验倒退 - 如果用了
outline: none又没补:focus-visible样式,键盘用户就彻底“失焦” - 移动端 Safari 对
:focus-visible支持弱,建议 fallback 到 JS 检测event.detail === 0(键盘触发时 detail 为 0)
最常被跳过的不是技术点,而是验证环节:不真关掉鼠标、只用键盘走一遍表单,就永远不知道哪个 div 少了 tabindex,哪个弹窗关闭后没还焦点,哪条快捷键在输入框里按了却没反应——这些都得靠实操暴露。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











