:focus仅对可聚焦元素生效,需确保元素原生可聚焦或设tabindex="0";:active仅为瞬态按压反馈,无法表示持久“当前项”状态;推荐用aria-current="page"+JS管理+CSS控制实现语义化高亮。

focus 伪类只对可聚焦元素生效,按钮默认可聚焦但需注意 tabindex
原生 <button> 元素默认支持 :focus,点击或按 Tab 键获得焦点时样式立即生效。但若按钮被包裹在 <div> 或用 <span> 模拟按钮,就无法触发 :focus,除非手动加 tabindex="0"。
常见错误是给非表单元素写 :focus 却没设 tabindex,结果样式完全不生效。
- 确保目标元素原生可聚焦(
<button>、<a href>、带tabindex的元素) - 避免用
tabindex="-1"—— 它允许脚本聚焦,但无法通过 Tab 键进入 - 移动端 Safari 对
:focus支持不稳定,常需配合ontouchstart或:focus-visible
:active 伪类只在鼠标按下/触摸瞬间生效,不能维持“当前项”状态
:active 是瞬态伪类:鼠标按下时匹配,松开即失效。它无法表达“这个按钮是当前选中项”的语义,只适合做按压反馈(比如颜色变深、位移 1px)。
如果你希望某个按钮长期高亮(比如导航栏中当前页面对应的按钮),:active 完全不合适,必须靠 JS 切换 class 或服务端渲染 class。
立即学习“前端免费学习笔记(深入)”;
-
:active不受 JavaScript 控制,无法用element.classList.add()激活 - 和
:focus同时存在时,:active优先级更高(如果样式冲突) - 真机触摸时,部分 Android 浏览器需
* { touch-action: manipulation; }才能可靠触发:active
真正实现“当前项高亮”的推荐方式:class + JS 状态管理
用 aria-current="page" 标记当前项,再配合 CSS 选择器控制样式,是最健壮的做法。它既支持屏幕阅读器,又不受交互方式限制(键盘、鼠标、触摸、JS 激活都生效)。
.nav-btn {
color: #666;
}
.nav-btn[aria-current="page"],
.nav-btn[aria-current="page"]:focus {
color: #007bff;
font-weight: bold;
}- 用 JS 切换
aria-current属性,而不是 toggleactiveclass —— 语义更明确 - 不要仅依赖
.activeclass,它对辅助技术无意义 - 若需键盘导航后保持高亮,记得在
keydown中同步更新aria-current
focus-visible 是更好的:focus替代方案,但需注意兼容性
:focus-visible 只在用户**明确通过键盘聚焦**时生效(比如按 Tab),避免鼠标点击后意外触发焦点样式。这对用户体验很关键——你肯定不想用户点一下按钮,它就留着蓝框不消失。
但它的兼容性有限:Chrome 86+、Firefox 83+、Safari 15.4+ 支持;旧版需用 focus-visible polyfill。
- 别用
:focus覆盖所有场景,优先考虑:focus-visible - 搭配
:focus:not(:focus-visible)可隐藏鼠标点击后的焦点环(谨慎使用,确保可访问性) - 某些定制组件(如 React 封装的 Button)可能拦截原生 focus 行为,需手动调用
element.focus()并确保tabIndex设置正确
CSS 里没有“当前项”的内置概念,所有持久高亮都得靠属性或 class 驱动。focus 和 active 是交互反馈,不是状态标识 —— 这个边界一旦混淆,后期维护和无障碍支持就会出问题。










