:focus本身有效,但视觉反馈常被重置CSS、outline:none、border替代不当或低对比度等导致“看不见”;必须用outline+outline-offset+高对比色提供稳定可访问焦点样式,并与:focus-visible按正确顺序配合。

直接说结论:仅写 :focus 样式不等于保障无障碍,真正起作用的是你是否提供了稳定、高对比、不被覆盖的视觉反馈——而且它必须在所有设备、所有浏览器、所有第三方样式环境下都生效。
为什么:focus样式经常“看不见”
不是 :focus 失效,而是视觉反馈被静默抹掉了:
- 重置 CSS(如 Normalize.css 或 Tailwind base)默认设了
outline: none,你写的a:focus { outline: 2px solid #0066cc; }被覆盖了 - 写了
*:focus { outline: none; }却没补任何替代样式——键盘用户立刻“失明” - 用
border替代outline,但没加outline-offset,导致焦点框被父容器overflow: hidden剪掉,或挤出布局 - iOS Safari 默认给
<input>加蓝光,一旦设了outline就消失,而你补的样式对比度又不足(WCAG 要求至少 3:1)
:focus 和 :focus-visible 必须配合使用,且顺序不能错
单独依赖任一者都会破坏可访问性:
-
:focus总是触发(鼠标点、Tab 切、element.focus()都算),它是兜底层,必须提供基础可见样式 -
:focus-visible只在浏览器判断为“键盘导航意图”时才触发(如 Tab/Shift+Tab/Enter),适合做精细美化,但不能替代:focus - 声明顺序必须是:
button:focus { outline: none; }在前,button:focus-visible { outline: 2px solid #0066cc; }在后;否则旧浏览器里整个焦点样式会丢失 -
@supports selector(:focus-visible)在 Safari 15.3 及更早版本中会整块规则丢弃——你连降级样式都拿不到,别用它做条件加载
安全有效的:focus写法要点
绕过常见陷阱的最小可行方案:
立即学习“前端免费学习笔记(深入)”;
- 坚持用
outline,不用border:它不占布局空间,不会引发重排,且符合 WCAG 对“非侵入式聚焦指示”的要求 - 显式设置
outline-offset(如2px),避免被父容器overflow: hidden剪掉 - 颜色选高对比值,比如
#0066cc或#2d5d9f,别只靠色相区分(红绿色盲用户看不到) - 移动端 iOS Safari 需额外补足:一旦覆盖默认蓝光,就得手动保证尺寸(≥2px)和对比度(≥3:1)
- 禁用
!important:它会让屏幕阅读器用户的自定义样式或浏览器强制高对比模式失效
真正难的不是写对一行 input:focus,而是确保它在整个组件库、所有第三方 UI 框架、每种设备和辅助技术环境下都稳定可见。样式可能被覆盖十次,但只要有一次没 fallback,键盘用户就卡在页面中间找不到路。


















