:focus-visible更可靠,因它仅在Tab、Shift+Tab、Enter、Space等键盘导航时生效,而:focus对鼠标点击、触摸、JS聚焦均触发蓝框造成干扰;需禁用全局outline: none并显式设置outline样式,且声明顺序应为:focus先设基础样式、:focus-visible后覆盖。

为什么:focus-visible比:focus更可靠
:focus一触发就画轮廓,鼠标点、触摸点、JS调用element.focus()全算——但用户根本没按键盘,这时候蓝框只是干扰。而:focus-visible是浏览器自己判断“这次聚焦是不是键盘驱动的”,只在Tab、Shift+Tab、Enter、Space等真实键盘导航时生效。
怎么写才能让:focus-visible真正显示出来
直接写:focus-visible样式大概率没反应,关键在两件事:
- 别用
* { outline: none }这种全局清空,它会把:focus-visible的基础能力一起干掉 - 必须显式设置
outline或其他可感知样式,比如outline: 2px solid #007aff和outline-offset: 2px - 声明顺序不能错:先写
button:focus { outline: none; },再写button:focus-visible { outline: 2px solid #007aff; }——靠层叠降级,不是靠!important
哪些元素默认不触发:focus-visible
加了tabindex="0"不等于能用,浏览器有内置逻辑:
- ✅ 默认触发:
<input>、<textarea>、<button>、<select>、带tabindex="0"的<div> - ❌ 默认不触发:
<a>(无href)、<span>(即使有tabindex="0")、<label>(除非显式设tabindex) - ⚠️ 自定义组件(如
<div role="button">)必须配role+ 键盘事件监听,否则部分浏览器拒绝激活
兼容性坑和调试捷径
:focus-visible在Chrome 86+、Firefox 89+、Safari 15.4+原生支持;Safari 15.3及更早版本不识别,且旧版行为不稳定。更隐蔽的问题是:很多CSS框架或重置库(如旧版Bootstrap)悄悄覆盖了它的默认行为。
立即学习“前端免费学习笔记(深入)”;
调试时别反复切键盘,直接在DevTools里手动勾选元素的:focus-visible状态,看样式是否生效——这是最快验证方式。
最常被忽略的点:页面加载后JS调用element.focus()默认不算键盘导航,:focus-visible不匹配;若需强制触发,得用element.focus({ focusVisible: true })(Chrome 111+支持)。


















