:focus-visible 仅响应键盘导航,鼠标点击触发的是 :focus;应使用 :focus:not(:focus-visible) 关闭鼠标/触摸焦点轮廓,再用 :focus-visible 为键盘用户保留可访问性轮廓。

直接写 button:focus { outline: none; } 能关掉蓝框,但会破坏键盘用户可访问性——这不是 bug,是浏览器在帮你守 WCAG 合规底线。
为什么 button:focus-visible { outline: none; } 完全没用
这条规则在鼠标点击时根本不会触发::focus-visible 只响应键盘导航(Tab、Shift+Tab、Enter、Space),不响应鼠标或触摸。开发者工具里看到它“灰掉”,不是兼容性问题,是压根没匹配上。你真正想关的,是鼠标点下去那一刻的默认 outline,它走的是 :focus,不是 :focus-visible。
button:focus:not(:focus-visible) 才是关键开关
这个组合选择器精准命中“有焦点但非键盘触发”的场景,比如鼠标点击、触屏 tap、或 JS 调用 element.focus() 且无键盘上下文的情况。
- 必须按顺序声明:先定义通用
:focus样式(哪怕只是占位) - 再用
:focus:not(:focus-visible)关闭鼠标/触摸下的outline,例如outline: none; - 最后用
:focus-visible给键盘用户提供清晰轮廓,outline: 2px solid #007bff;这类值才有效,outline: 0或空规则会被忽略 - 旧版 Safari(:focus-visible,需用
focus-visiblepolyfill 或降级为柔和的outline: 1px dotted #999;
别漏掉 iOS 的点击瞬态高亮
iPhone 上按钮点击时的半透明蓝色遮罩,和 :focus 无关,是 WebKit 的 -webkit-tap-highlight-color 行为。
- 对可点击元素加
-webkit-tap-highlight-color: transparent; - 仅在真实触摸设备或 DevTools 的 touch 模拟模式下生效
- 它不影响焦点逻辑,只是移除视觉干扰,和
:focus-visible完全不重叠 - 如果按钮用了
background: linear-gradient等复杂背景,transparent可能导致点击时闪白,此时改用rgba(0,0,0,0)
去掉蓝框后,键盘用户就“看不见焦点在哪”了
这是最常被跳过的实操细节:移除 outline 不等于可以不提供焦点反馈。WCAG 2.4.7 明确要求焦点必须可见。
- 替代方案优先用
box-shadow:它不侵占布局空间,且可设模糊半径增强辨识度 - 避免只靠颜色变化(如
background-color),色弱用户可能无法识别 - 若用边框替代,注意
border会改变元素尺寸,需配合box-sizing: border-box - 对 Bootstrap 用户,别只改
.btn:focus,.form-control:focus、.custom-select:focus同样要处理
真正麻烦的不是写对一行 CSS,而是混合交互场景下焦点状态的连续性——比如鼠标点开弹窗后按 Tab,焦点是否自然落到第一个可操作项?这种边界必须用真实键盘反复验证,不能只靠鼠标点几下就认为“没问题”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











