:focus必须为可聚焦元素提供高对比、不依赖颜色的视觉反馈,否则键盘用户将无法导航;默认outline不可随意移除,应改用outline-offset≥2px、对比度≥4.5:1的替代样式。

直接结论:用 :focus 给可聚焦元素加清晰、高对比的视觉反馈,不是“锦上添花”,而是键盘用户能正常操作页面的底线。
为什么移除默认 outline 后键盘用户就“迷路”了
很多项目一上来就写 * { outline: none } 或给 button:focus 直接设 outline: 0,结果是:Tab 键能切到按钮,但屏幕上毫无变化。键盘用户不知道焦点在哪,等于关掉了他们的导航地图。
- 浏览器默认
outline是为可访问性设计的,不是“丑”,而是“可见性优先” - 色盲、低视力用户依赖轮廓的粗细和位置,而非颜色差异
- 仅靠边框变色(如
border-color: blue)在深色背景或高对比主题下可能完全不可见
:focus 样式必须满足的三个硬条件
不是随便加个 box-shadow 就算完事。真正起作用的 :focus 样式得同时扛住这三条:
- 有足够对比度:建议使用
outline而非仅靠border,宽度 ≥ 2px,颜色与背景差值 ≥ 4.5:1(可用 DevTools 的无障碍检查器验证) - 带偏移量(
outline-offset),避免和元素边缘粘连,尤其对圆角按钮或图标按钮 - 不遮挡内容:别用
background-color覆盖文字,慎用z-index导致被其他层盖住
推荐写法:button:focus { outline: 2px solid #0066cc; outline-offset: 2px; }
哪些元素写了 :focus 也没用?
不是所有 HTML 元素天然支持 :focus,也不是加了 tabindex 就自动生效:
- ✅ 默认可聚焦:
<input>、<textarea></textarea>、<button></button>、<a href></a>、<select></select> - ❌ 默认不可聚焦:
<div>、<code><span></span>、<p></p>—— 即使加了tabindex="0",也需确保没被disabled或display: none - ⚠️ 自定义组件(如用
<div role="button"> 实现的按钮)必须配 <code>tabindex="0"+role+ 键盘事件监听(Enter/Space),否则部分浏览器(尤其是 Safari)拒绝触发:focus和
:hover、:active混用时最容易踩的坑很多人把
:focus和:hover写成同一套样式,结果鼠标悬停时出现轮廓,显得突兀;或者把:focus放在:hover后面,导致鼠标点击后焦点样式被覆盖。- 顺序必须是
:hover→:focus→:active(LVHA 原则),否则:focus可能被:hover覆盖 - 别写
a:hover:focus这种组合——它只匹配“既悬停又聚焦”的极少数场景(比如鼠标移到链接上再按 Tab),几乎无实际意义 - 移动端触屏设备中,
:focus可能在点击后短暂触发又消失,建议配合:focus-visible分离逻辑,而不是强行统一
真正难的不是写几行 CSS,而是坚持让每个可交互元素都有明确、一致、不依赖颜色的焦点提示——这点在暗色模式、高对比主题、屏幕阅读器环境下会立刻暴露出来。
- 顺序必须是











