:focus-visible 不能替代 :focus,因其仅在键盘导航时生效,需与:focus配合使用,且:focus-visible必须置于:focus之后;须先用:focus设默认无显眼样式,再用:focus-visible为键盘用户恢复焦点指示。

focus-visible 为什么不能直接替代 :focus
因为 :focus-visible 只在「用户明确通过键盘操作(如 Tab、Shift+Tab、方向键)获得焦点」时生效,而鼠标点击或触摸后触发的 :focus 不会匹配它。浏览器用启发式策略判断是否“可见焦点应被强调”,比如:用户刚点完按钮就立刻按 Tab,此时可能跳过 :focus-visible;但纯键盘导航全程都会命中。这意味着你不能只写 :focus-visible 就指望覆盖所有焦点场景——它不是 :focus 的增强版,而是互补机制。
必须配合 :focus 使用,且顺序不能错
样式层叠规则要求把 :focus-visible 放在 :focus 后面,否则会被覆盖。更关键的是:你要先给所有可聚焦元素定义基础 :focus 样式(比如统一移除 outline),再用 :focus-visible 单独加回键盘用户的轮廓线或高亮。否则鼠标用户点击后看不到任何焦点反馈,违反可访问性要求。
常见错误写法:
button:focus { outline: 2px solid #007aff; }
button:focus-visible { outline: none; } /* 错!这会让键盘用户失去焦点指示 */
正确逻辑是:
-
:focus设为「默认不显眼」(例如outline: none或outline: 1px dotted transparent) -
:focus-visible显式恢复视觉焦点提示(比如outline: 2px solid #007aff) - 确保该选择器出现在
:focus规则之后
需要降级处理 focus-visible 不支持的浏览器
旧版 Safari(:focus-visible,部分安卓 WebView 表现也不稳定。不能只依赖它做焦点区分。推荐用 @supports 检测并包裹规则:
@supports (selector(:focus-visible)) {
button:focus {
outline: none;
}
button:focus-visible {
outline: 2px solid #007aff;
outline-offset: 2px;
}
}
/* 不支持时回退到传统 focus 样式 */
button:focus {
outline: 2px solid #007aff;
outline-offset: 2px;
}
注意:@supports selector() 是关键,仅用 @supports (focus-visible) 会误判(CSS 属性检测不适用于伪类)。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
自定义组件里要手动触发 focus-visible 的判定逻辑
原生 button、input 等元素由浏览器自动管理 :focus-visible 的触发时机,但自定义组件(如用 div role="button" 实现的按钮)不会自动获得该行为。你需要监听 keydown 事件,在非鼠标事件首次触发焦点时添加临时 class,模拟效果:
element.addEventListener('keydown', (e) => {
if (e.key === 'Tab' || e.key === 'Enter' || e.key === ' ') {
element.classList.add('js-focus-visible');
}
});
element.addEventListener('mousedown', () => {
element.classList.remove('js-focus-visible');
});
然后在 CSS 中写:
button.js-focus-visible:focus {
outline: 2px solid #007aff;
}
这种手动方式无法 100% 复现浏览器原生逻辑(比如连续 Tab 导航中的状态保持),但能解决大部分可访问性缺口。
真正难的是让 focus-visible 的判定边界和你的交互节奏对齐——比如一个带下拉菜单的组合控件,键盘打开后菜单项获得焦点,但用户期望整个组合区域仍保持 visible 状态,这时候就得靠 JS 维护状态,而不是只靠 CSS 伪类。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










