样式聚焦

焦点指示器(通常用“对焦环”表示)可标识当前的 网页上的特定元素对于无法使用鼠标的用户, 指标极为重要,因为它可作为 鼠标指针。

如果浏览器的默认焦点指示器与您的设计冲突,您可以使用 来调整其样式切记要为键盘用户着想!

使用 :focus 始终显示焦点指示器

:focus 伪类会在某个元素获得焦点时应用,而不考虑输入源 设备(鼠标、键盘、触控笔等)或将其对焦的方法。例如: 下面的 <div> 具有使其可聚焦的 tabindex。它还具有 :focus 状态的自定义样式:

div[tabindex="0"]:focus {
  outline: 4px dashed orange;
}

无论您是使用鼠标点击点击,还是使用键盘按 Tab 键, <div> 看起来始终相同。

遗憾的是,浏览器与其应用焦点的方式可能不一致。还是 不是某个元素获得焦点可能取决于浏览器和 系统。

例如,下面的 <button> 还具有其 :focus 的自定义样式 状态。

button:focus {
  outline: 4px dashed orange;
}

在 macOS 上,如果您在 Chrome 中使用鼠标点击 <button>,您应该会看到 自定义焦点样式但是,如果你将焦点移至某个 在 macOS 上,点击 Safari 中的 <button>。这是因为 在 Safari 中,当您点击元素时,该元素没有获得焦点。

由于焦点的行为不一致,可能需要进行一些测试 以确保您的焦点样式能被用户接受

使用 :focus-visible 选择性地显示焦点指示器

新的 :focus-visible 伪类会在某个元素获得焦点并且 浏览器通过启发式算法确定显示焦点指示器 对用户有益。特别是,如果最近一次用户互动 是通过键盘进行的,并且按键操作不包含 Meta 键 ALT / OPTION, 或 CONTROL 键,则 :focus-visible 将匹配。

下例中的按钮将有选择地显示焦点指示器。如果 那么结果会不同于第一次使用 按 Tab 键即可转到该窗格。

button:focus-visible {
  outline: 4px dashed orange;
}

使用 :focus-within 为聚焦元素的父项设置样式

通过 :focus-within 伪类会在某个元素自身收到该元素时, 焦点,或者该元素内的其他元素获得焦点时。

它可用于突出显示网页的某个区域,以绘制 用户对该区域的关注度例如,下面的表单同时获得焦点 当表单本身被选中时,以及其任何单选按钮被选中时 已选择。

form:focus-within {
  background: #ffecb3;
}

何时显示焦点指示器

一个好的做法是问自己: 使用移动设备,您认为它会显示键盘吗?”

如果答案是肯定的,则该控件可能应该始终显示焦点。 指示符,无论使用何种输入设备来聚焦它。一个很好的例子是 <input type="text"> 元素。用户需要将输入发送到 元素,而不管输入元素最初是如何接收的, 因此始终显示焦点指示器很有帮助。

如果答案是否定的,那么控件便可选择性地显示焦点 指示器。<button> 元素就是一个很好的例子。如果用户使用 鼠标或触摸屏,则操作已完成,且焦点指示标志不得 。不过,如果用户使用键盘进行导航,则很有用。 显示焦点指示标志,以便用户决定是否要 使用 ENTERSPACE 键点击控件。

避免使用 outline: none

坦率地说,浏览器决定何时绘制焦点指示器, 令人感到困惑使用 CSS 更改 <button> 元素的外观,或将 tabindex 元素会导致浏览器的默认焦点环行为 。

一种很常见的反模式是使用 CSS 移除焦点指示器,例如:

/* Don't do this!!! */
:focus {
  outline: none;
}

若要解决此问题,更好的方法是结合使用 :focus:focus-visible polyfill。下面的第一个代码块演示了 该 polyfill 的运作方式,其下方的示例应用提供了一个使用 polyfill 来更改按钮上的焦点指示器。

/*
  This will hide the focus indicator if the element receives focus via the
  mouse, but it will still show up on keyboard focus.
*/
.js-focus-visible :focus:not(.focus-visible) {
  outline: none;
}

/*
  Optionally: Define a strong focus indicator for keyboard focus.
  If you choose to skip this step, then the browser's default focus
  indicator will be displayed instead.
*/
.js-focus-visible .focus-visible {
  
}