:focus不适用于无障碍焦点样式,因为它在键盘聚焦和鼠标点击时均触发,导致鼠标用户看到突兀轮廓线;应改用:focus-visible实现仅键盘触发的焦点样式。

为什么:focus不适用于无障碍焦点样式
:focus 会在键盘聚焦和鼠标点击后都触发,导致鼠标用户看到突兀的轮廓线。这不是 bug,是规范行为——但对无障碍体验有害:鼠标操作本不该激活“键盘导航”样式。浏览器无法区分焦点来源,:focus 一视同仁,结果就是你加了样式,用户用鼠标点按钮时也强制显示,干扰视觉动线。
常见错误现象:button:focus { outline: 2px solid blue; } → 鼠标点击按钮瞬间出现蓝边,松开后残留(尤其在 Safari 中),用户以为自己误操作了。
使用场景:所有需要明确键盘导航路径的交互元素(button、a、input、带 tabindex 的容器)。
如何正确启用:focus-visible
:focus-visible 是浏览器原生判断“当前焦点是否由键盘触发”的伪类,无需 JS 拦截事件或维护状态。但它默认不回退,且部分旧浏览器不支持。
实操建议:
- 始终搭配
:focus使用,提供降级:先写:focus(窄范围、低权重),再写:focus-visible(覆盖它) - 不要只写
:focus-visible—— 否则 Firefox 旧版、Safari 15.4 之前会完全失效 - 避免用
!important强行覆盖,靠选择器权重自然接管即可
示例(安全写法):
button:focus {
outline: none;
}
button:focus-visible {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
Chrome/Firefox/Safari 的兼容性差异
不是“支持 or 不支持”,而是“何时开始识别键盘焦点”的策略不同:
- Chrome 86+ 和 Edge 86+:稳定支持,策略较宽松,Tab/Shift+Tab/Enter/Space 都触发
- Firefox 89+:支持,但对某些自定义
contenteditable元素响应略滞后 - Safari 15.4+:支持,但早期版本(15.0–15.3)仅在“强制开启辅助功能”时才启用
:focus-visible
性能影响几乎为零——它是 CSS 引擎原生逻辑,不触发重排,也不依赖 JS 监听。
容易被忽略的边界情况
三个真实踩坑点:
- 移动端 Safari 在触摸后首次 Tab 导航,可能不触发
:focus-visible(系统未进入“键盘模式”),需测试真机 - 通过
element.focus()JS 聚焦时,Chrome 默认不视为键盘焦点,除非同时设置{ preventScroll: false, focusVisible: true }(仅 Chromium 115+) - 如果全局重置了
* { outline: none; },必须显式为:focus-visible恢复 outline,否则所有键盘焦点都不可见
最复杂的地方不在写法,而在于验证:得用真实键盘 Tab 测试,不能靠鼠标模拟;得在 iOS + VoiceOver、Windows + NVDA 下交叉确认——视觉样式只是表层,背后是整个焦点管理链路是否连贯。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











