伪类 :focus-visible
平常很难引起注意,因为如今大多数细节操作都由组件库处理。然而,当你需要自己编写按钮组件时,这个伪类对于提升用户体验非常重要。
曾经的 :focus-visible
在文章 CSS :focus-visible 伪类让我感动哭了 中提到,在 Chrome 浏览器下,一些元素在使用鼠标点击时可能会出现意料之外的焦点轮廓。但是我们不能简单地使用 outline: none;
来处理这个问题,因为我们还需要考虑键盘导航对焦点的触发。
然后,:focus-visible
伪类出现了,它恰好解决了这个问题,因为它只对键盘导航触发的焦点有效。
以下 CSS 代码的作用是在不影响键盘导航触发焦点轮廓的情况下,去除鼠标点击触发的焦点轮廓:
:focus:not(:focus-visible) {
outline: 0;
}
现在的 :focus-visible
距离文章发表日期已经过去近 4 年的时间,现在在使用 Chrome
浏览器点击文中提到的元素时,不会再出现意料之外的焦点轮廓。因此,对这些元素使用 :focus:not(:focus-visible)
已经不再必要。
然而,如果你只想为鼠标点击状态下的按钮编写样式,使用 :focus:not(:focus-visible)
仍然非常有必要。因为如果只使用 :focus
,样式也会应用于通过键盘导航触发的焦点。
当然,有些人采取激进的方式,只使用 :focus-visible
而不使用 :focus
,CSS focus-visible is my new default
Antd Button
在查看 Antd Button 的样式代码 时,我发现了两个有趣的点:
- button 的样式中并没有使用
:focus
伪类。这可能是出于对按钮在点击后能够恢复到未点击状态的考虑。当然,这也取决于组件的设计语言,因为有些按钮在设计时并不需要在点击后恢复到未点击状态。 :focus-visible
伪类出现在genFocusStyle
函数中
尽管没有使用 :focus
,但并不意味着没有处理点击状态。在 Antd 中,使用 JavaScript 动态插入和移除一个 <div/>
来模拟点击状态(源码)。
有了 JavaScript 处理鼠标点击状态,使用 :focus-visible
就更加纯粹,只需要关注键盘导航触发的焦点即可。
在 genFocusStyle
函数中生成了与 :focus-visible
相关的代码(genFocusStyle 被调用位置、genFocusStyle 函数)
通过这种方式,Antd 可以更好地处理按钮组件的焦点状态,提升用户体验。