:focus:not(:focus-visible)才是清除鼠标点击黑框的正确选择器,它精准捕获非键盘触发的焦点状态;必须按button:focus、:focus:not(:focus-visible)、:focus-visible顺序声明,且:focus-visible需有显式outline值。

button:focus:not(:focus-visible) 才是清除鼠标点击黑框的正确选择器
单独写 button:focus-visible { outline: none; } 完全无效——浏览器在鼠标点击时根本不会匹配 :focus-visible,这条规则在 DevTools 里直接变灰,蓝框/黑框照旧出现。真正起作用的是 :focus:not(:focus-visible),它精准捕获“有焦点但非键盘触发”的场景,比如鼠标点、触摸 tap、或 JS 调用 element.focus() 后无键盘上下文的状态。
必须按顺序声明三段规则,缺一不可:
-
button:focus写在最前,定义基础焦点样式(哪怕只是outline: 1px dotted #999;) -
button:focus:not(:focus-visible)紧跟其后,专门设为outline: none; -
button:focus-visible放最后,显式声明可访问轮廓(outline: 2px solid #0066cc;,不能是0或空)
哪些元素上 :focus-visible 根本不会触发?别白费劲写规则
不是加了 tabindex="0" 就能用 :focus-visible。浏览器只对语义明确、需焦点提示的控件启用该伪类:
- ✅ 默认支持:
<input>、<textarea></textarea>、<button></button>、<select></select>、带tabindex且含role="button"的<div> <li>❌ 基本不触发:<code><a></a>(无href)、<span></span>(哪怕写了tabindex="0")、<img>(本身不可聚焦,黑框来自父容器) - ⚠️ 自定义组件要小心:用
<div tabindex="0"> 模拟按钮,但没加 <code>role或没监听Enter/Space,旧 Safari 可能跳过匹配iOS 上的半透明蓝 overlay 不是 :focus-visible 能管的
你在 iPhone 上点按钮看到的蓝色遮罩,和
:focus或:focus-visible完全无关——这是 WebKit 的-webkit-tap-highlight-color行为。它和焦点逻辑并行,互不影响。要关掉它,得单独处理:
- 对可点击元素加
-webkit-tap-highlight-color: transparent; - 适用于
<button></button>、<a></a>、或带onclick的容器 - 漏掉这句,点击反馈会混乱;指望
:focus-visible管这事,它连碰都不碰
Element Plus 的
.el-dropdown黑框怎么去?别全局重置Element Plus 2.2.31+ 更新后,下拉触发时的黑框常来自
.el-tooltip__trigger:focus或类似内部触发器。直接写*:focus { outline: none; }会破坏所有可访问性,绝对不行。安全做法是精准定位、局部覆盖:
- 用 DevTools 查找实际获得焦点的类名(常见如
.el-dropdown__caret、.el-tooltip__trigger) - 写带命名空间的选择器,例如
.my-dropdown .el-tooltip__trigger:focus:not(:focus-visible) { outline: none; } - 同时补上
.my-dropdown .el-tooltip__trigger:focus-visible { outline: 2px solid #007aff; },保证键盘用户路径清晰
顺序错、选择器太宽、漏掉
:focus兜底,这三个点最容易被忽略,一漏就导致鼠标用户失焦、键盘用户无反馈、iOS 上还有双层高亮。 - 对可点击元素加











