:focus样式必须强于:hover,因焦点是导航锚点而悬停只是临时探查;两者须分开定义:focus用高对比outline确保键盘用户可见,hover可轻量微调,且需单独处理hover:focus组合态。

必须让 :focus 样式在视觉上等价于或强于 :hover 效果,否则键盘用户会感知不到交互反馈。
为什么:hover和:focus不能用同一套样式逻辑
鼠标悬停是临时探查行为,焦点是导航锚点——两者语义不同。很多团队直接写 a:hover, a:focus 一把梭,结果鼠标用户看到多余轮廓、键盘用户又因样式太弱而找不到当前项。
- :hover 触发条件宽松:只要鼠标进入渲染区域就生效,哪怕元素没
tabindex或不可聚焦 - :focus 只对可聚焦元素生效(
<a></a>、<button></button>、带tabindex的<div> 等),且依赖浏览器焦点管理 <li>重置 CSS(如 Normalize、Tailwind base)常默认设 <code>*:focus { outline: none; },你写的a:focus规则若没提高优先级或加!important,大概率被覆盖 - 先写
a:focus基础样式:用outline+outline-offset(如outline: 2px solid #0066cc; outline-offset: 2px;),确保不占布局、不被overflow: hidden剪掉 - 再写
a:hover:可只改background-color或color,避免加 outline(否则鼠标用户看到双焦点框) - 若需 hover + focus 同时生效(比如按钮被键盘聚焦且鼠标悬停),用
button:hover:focus单独定义,别混进通用规则 - 所有
:focus样式必须加transition(如transition: outline 0.15s ease;),否则焦点跳转时会“闪断” - 不要依赖系统默认蓝光,必须主动提供等效视觉反馈
- 在
@media (hover: hover)下可启用更精细的:hover效果;在触屏设备上,:focus样式要更粗、更亮(比如outline-width: 3px) - 测试时禁用鼠标,纯用 Tab 键导航,看焦点是否连续、不跳项、不消失
- 第三方 UI 库(如 Ant Design、Mantine)常自带 focus 样式,但容易被项目全局 reset 覆盖——检查 computed styles 里的
outline是否真生效,而不是只看 rules 面板
:hover 和 :focus 的样式必须分开定义
不是“能不能一起写”,而是“必须拆开控制”。基础原则::focus 提供可靠、高对比、不依赖颜色的反馈;:hover 可以更轻量、带动画或仅颜色微调。
移动端和 Safari 的:focus陷阱
iOS Safari 在聚焦时默认加蓝光,但只要你写了任何 outline,它就彻底消失——而你的新样式很可能对比度不足、尺寸太小,导致键盘用户在 iPad 上完全看不到焦点。
真正难的不是写出 input:focus 这一行,而是确保它在 Web Components 封装内、Shadow DOM 里、iframe 子页面中、以及开启“强制高对比模式”的 Windows 系统下,依然稳定可见。











