2021焦点可见解决方案
注意 1:在下面列出的 3 个选项中,按钮的行为方式相同(单击时没有聚焦环),但选择和输入的默认行为略有不同。只有选项 3 始终移除按钮、输入和选择周围的聚焦环。请比较所有方法并确保您了解其中的含义。
注意 2:由于 CSS 的级联特性,CSS 规则的顺序很重要。
注 3:任何方法仍然存在一些可访问性问题focus-visible
。也就是说,在浏览器公开配置以让用户选择何时显示可见的焦点环之前,应该认为焦点可见的可访问性比一直使用焦点环更糟糕,但比:focus {outline:none}
这个问题的其他答案中提到的有害方法要好. 有关更多详细信息,请参阅此答案底部的“关于可访问性的说明”部分。
选项 1:使用:focus-visible
伪类
:focus-visible
伪类可用于为不通过键盘导航(即,通过触摸或鼠标单击)的用户删除按钮和各种元素上的轮廓和焦点环。
警告:截至 2021 年,:focus-visible
伪类**在现代浏览器中得到广泛支持,但在边缘浏览器上失败**。如果旧浏览器支持很重要,那么下面选项 2 中的 Javascript polyfill 是最接近的近似值。
/**
* Remove focus styles for non-keyboard focus.
*/
:focus:not(:focus-visible) {
outline: 0;
box-shadow: none;
}
/**
* Cross-browser styles for explicit focus via
* keyboard-based (eg Tab) navigation or the
* .focus-visible utility class.
*/
:focus,
.focus-visible:focus:not(:focus-visible) {
outline: 0;
box-shadow:
0 0 0 .2rem #fff,
0 0 0 .35rem #069;
}
<h3>Defaults:</h3>
<button>Foo</button>
<input type="button" value="Bar"/>
<select><option>Baz</option></select>
<input type="text" placeholder="Qux"/>
<textarea placeholder="Quux" rows="1"></textarea>
<h3>Force focus on click:</h3>
<button class="focus-visible">Foo</button>
<input class="focus-visible" type="button" value="Bar"/>
<select class="focus-visible"><option>Baz</option></select>
<input class="focus-visible" type="text" placeholder="Qux"/>
<textarea class="focus-visible" placeholder="Quux" rows="1">
</textarea>
选项 2:使用.focus-visible
polyfill
该解决方案使用普通的 CSS 类而不是上面提到的伪类,并且具有更广泛的浏览器支持(2021 年)。它需要在您的 HTML 中添加 1 或 2 个 Javascript;一个用于官方的焦点可见 polyfill,另一个用于不支持 classList的旧浏览器。
注意:在 Chrome 中,polyfill 处理选择的方式似乎与原生:focus-visible
伪类不同。
/**
* Cross-browser focus ring for explicit focus
* via keyboard-based (eg Tab) navigation or the
* .focus-visible utility class.
*/
:focus {
outline: 0;
box-shadow:
0 0 0 .2rem #fff,
0 0 0 .35rem #069;
}
/**
* Remove focus ring for non-explicit scenarios.
*/
:focus:not(.focus-visible) {
outline: 0;
box-shadow: none;
}
<h3>Defaults:</h3>
<button>Foo</button>
<input type="button" value="Bar"/>
<select><option>Baz</option></select>
<input type="text" placeholder="Qux"/>
<textarea placeholder="Quux" rows="1"></textarea>
<h3>Force focus on click:</h3>
<button class="focus-visible">Foo</button>
<input class="focus-visible" type="button" value="Bar"/>
<select class="focus-visible"><option>Baz</option></select>
<input class="focus-visible" type="text" placeholder="Qux"/>
<textarea class="focus-visible" placeholder="Quux" rows="1">
</textarea>
<!-- place this code just before the closing </html> tag -->
<script src="https://cdn.polyfill.io/v2/polyfill.js?
features=Element.prototype.classList"></script>
<script src="https://unpkg.com/focus-visible"></script>
选项 3:使用全局键导航与鼠标导航状态
焦点可见的逆解决方案是在 上禁用轮廓mousemove
,并在 上启用它们keydown -> "Tab"
。在这种情况下,您必须指定哪些元素应该显示轮廓,而不是指定哪些元素不应该显示轮廓。
document.addEventListener("mousemove", () =>
document.body.classList.remove("focus-visible")
);
document.addEventListener("keydown", ({key}) =>
(key === "Tab") && document.body.classList.add("focus-visible")
);
/**
* Cross-browser focus ring for explicit focus
* via keyboard-based (eg Tab) navigation or the
* .focus-visible utility class.
*/
:focus {
outline: 0;
box-shadow:
0 0 0 .2rem #fff,
0 0 0 .35rem #069;
}
/**
* Remove focus ring for non-explicit scenarios.
*/
body:not(.focus-visible) :focus:not(.focus-visible) {
outline: 0 !important;
box-shadow: none !important;
}
<h3>Defaults:</h3>
<button>Foo</button>
<input type="button" value="Bar"/>
<select><option>Baz</option></select>
<input type="text" placeholder="Qux"/>
<textarea placeholder="Quux" rows="1"></textarea>
<h3>Force focus on click:</h3>
<button class="focus-visible">Foo</button>
<input class="focus-visible" type="button" value="Bar"/>
<select class="focus-visible"><option>Baz</option></select>
<input class="focus-visible" type="text" placeholder="Qux"/>
<textarea class="focus-visible" placeholder="Quux" rows="1">
</textarea>
关于可访问性的说明
删除所有焦点环是一个已知:focus { outline: none; }
的:focus { outline: 0; }
可访问性问题,从不推荐。此外,可访问性社区中的一些人宁愿你永远不要删除焦点环轮廓,而是让所有东西都有一个:focus
样式——如果样式合适,要么是有效的outline
,要么是有效的。box-shadow
最后,可访问性社区中的一些人认为,开发人员不应该:focus-visible
在他们的网站上实现,直到所有浏览器都实现并公开用户偏好,让人们选择是否所有项目都应该是可聚焦的。我个人并不赞同这种想法,这就是为什么我提供了这个我觉得比有害的解决方案要好得多的解决方案:focus { outline:none }
。我认为这:focus-visible
是设计关注点和可访问性关注点之间的快乐媒介。截至 2022 年,Chrome 浏览器已经公开了设置焦点可见性样式的用户偏好,但 FireFox 没有。
资源:
演示: