:focus仅对可聚焦元素生效,如input、button、a[href]等,div或span需加tabindex="0";hover与focus样式按声明顺序叠加,:focus-visible更适配键盘操作;移除outline必须提供等效视觉反馈。

focus伪类触发条件与可聚焦元素限制
只有能获得键盘焦点的元素才响应 :focus,比如 <input>、<button>、<a href>,而 <div> 默认不响应,除非加了 tabindex 属性。
常见错误是给 <span> 或无 tabindex 的 <div> 直接写 :focus 样式,结果完全不生效。
- 确保元素原生可聚焦,或显式设置
tabindex="0" - 避免对
tabindex="-1"元素依赖:focus视觉反馈——它只能通过 JS.focus()触发,无法用 Tab 键进入 - 移动端 Safari 对
:focus支持较弱,常需配合ontouchstart或role="button"补充逻辑
hover与focus共存时的样式覆盖逻辑
CSS 选择器权重相同的情况下,后声明的规则会覆盖先声明的。但更关键的是:用户同时满足 hover 和 focus(比如鼠标悬停后点击输入框),此时两个伪类都为真,浏览器会按层叠顺序应用样式。
例如下面这段代码中,input:focus 的边框颜色最终是红色,不是蓝色:
立即学习“前端免费学习笔记(深入)”;
input:hover {
border-color: blue;
}
input:focus {
border-color: red;
}
- 若想让 focus 样式「强制优先」,可提升选择器权重,如写成
input:focus:hover或input:focus放在input:hover后面 - 注意
:focus-visible是更现代的替代方案,它只在键盘操作触发 focus 时生效,能避免鼠标悬停时意外激活 focus 样式 - 不要依赖
:hover:focus来做「仅鼠标悬停且聚焦」的效果——多数浏览器不支持该组合(focus 状态在鼠标点击后才建立,hover 已结束)
去除默认焦点轮廓(outline)的安全替代方案
很多人直接写 *:focus { outline: none; } 来“美化”焦点样式,但这会破坏可访问性——键盘用户将彻底失去焦点位置提示。
- 必须提供等效视觉反馈:用
box-shadow、border或背景色变化替代outline - 推荐用
:focus-visible有选择地移除 outline:button:focus { outline: none; } button:focus-visible { outline: 2px solid #007bff; } - Chrome / Firefox 默认 outline 偏细且对比度低,建议至少设为
outline: 2px solid并确保色值满足 WCAG AA 对比度要求
移动端 touch 设备下的 hover/focus 行为差异
iOS 和 Android 浏览器对 :hover 支持有限:通常只在第一次触摸后临时激活一次,之后失效;:focus 在软键盘弹出时才稳定触发。
- 不要把核心交互反馈(如按钮按下态)只依赖
:hover,务必补充:active或 JS 类控制 - 在 iOS 上,
<meta name="viewport" content="width=device-width, initial-scale=1">缺失会导致:hover完全不工作 - 某些安卓 WebView 会把点击事件延迟 300ms 并模拟 hover,导致视觉反馈滞后——可用
touch-action: manipulation缓解


















