2021 年仅实现键盘样式的最佳方法是什么?

时间:2021-04-20 23:46:49

标签: javascript html css focus accessibility

通过 CSS outline: none; 从可交互元素(例如按钮)中删除轮廓一直是一种常见做法,因为大多数时候它看起来与品牌无关,但它阻碍了可访问性并使依赖在键盘导航上。

问题是我还没有找到一种简单的方法来区分鼠标/键盘之间的焦点事件源,并且单击以及键盘选项卡元素将触发焦点状态。

我知道这个问题一直是个hot topic,但是大多数来源已经有好几年了,所以我将展示我发现的关于如何实现仅键盘焦点的主要 4 种方法,每种方法都有自己的优缺点:

  1. “作弊”方法,Target.com等一些网站的悬停和聚焦样式相同,这种设计选择给了他们根本不需要移除焦点轮廓的选项。

优点:解决了问题。

缺点:设计选项有限。

button {
  width: 180px;
  height: 60px;
  background: #999;
  border: none;
}

button:focus,
button:hover { 
  outline: 5px solid green; 
}
<button>Click or Tab me!</button>

  1. JS 解决方案,Apple.com 等网站使用 ally.js 向其可交互元素添加 data-focus-method 属性。 what-input 也非常有名,与其他各种 polyfills 一起做得很好。

优点:可以在所有浏览器中正常运行,无论设计如何都可以实现。

缺点:需要额外的 http 请求来获取 .js 文件,与其他解决方案相比,JS 对性能的影响更大。

ally.style.focusSource().current()
button {
  width: 180px;
  height: 60px;
  background: #999;
  border: none;
  outline: none;
}

html[data-focus-source="key"] button:focus {
  outline: 5px solid green;
}
<button>Click or Tab me!</button>
<script src="https://cdn.jsdelivr.net/ally.js/1.4.1/ally.min.js"></script>

  1. :focus-within 优雅解决方案的圣杯。 :focus-visible 基本上是 :focus 的纯键盘版本,并且已经在 most modern browsers(以前的 :focus-ring)上慢慢推出。

优点:CSS 解决方案,性能简单,易于实施。

缺点:浏览器支持更好,但在 Safari 尚未加入的情况下仍然不理想。

button {
  width: 180px;
  height: 60px;
  background: #999;
  border: none;
  outline: none;
}

button:focus-visible {
  outline: 5px solid green;
}
<button>Click or Tab me!</button>

  1. Roman Komarov tabindex="-1" hack 表明我们可以通过在 span 元素(技术上有效的 HTML)中添加 button 然后赋予该跨度 {{1 }} 和不同的焦点样式。

优点:不涉及 JS,似乎适用于所有浏览器。

缺点:需要网站上所有按钮和链接内的垃圾邮件跨度,需要将填充从按钮/链接移动到内部跨度,需要调整各种跟踪标签,例如 gtm。

tabindex="-1"
button {
  width: 180px;
  height: 60px;
  background: #999;
  border: none;
  outline: none;
}

button > span {
  display: flex;
  justify-content: center;
  height: 100%;
  align-items: center;
}

button:focus {
  outline: 0;
}

button:focus > span {
  outline: 5px solid green;
}

[tabindex="-1"]:focus {
  outline: none !important;
}

现在的问题是,是否有更好或更简单的方法来实现此功能?是否有我缺少的行业标准?

2 个答案:

答案 0 :(得分:2)

现在的问题是,是否有更好或更简单的方法来实现此功能?是否有我缺少的行业标准?

简短回答:不,如果您的目标是“完美”(它在所有浏览器中的工作方式完全相同),您基本上已经在此处列出了您的选项。

然而,正如您所说,所有 4 个选项都有缺点。

就我个人而言,我会选择“最适合”的解决方案,在这种情况下,某些用户可能会在点击时获得焦点指示器,但大多数新浏览器都会妥善处理:

button:focus { 
outline: 3px solid #333;
outline-offset: 3px;
 }
button:focus:not(:focus-visible) {
    outline: none;
    outline-offset: 0;
}
<button>A test</button>
<button>Another test</button>

此解决方案的缺点?

Safari 仍会在点击时显示焦点指示器..... 没关系!

Safari 最终会赶上并使用 :focus-visible。在那之前,上面的方法是确保支持 :focus-visible 的浏览器按预期运行而不支持它的浏览器回退到在点击时提供焦点指示器的最简单方法。

但它必须是完美的

然后我会使用一个基于支持条件加载的 polyfill。

This answer details how to detect support for :focus-visible

此时您可以有条件地加载 a :focus-visible polyfill(3.5kb gzipped)。

我个人不喜欢这个解决方案,因为你必须改变你所有的 CSS....但我并不像大多数人那样被点击时显示的焦点指示器所困扰,所以我可能会有偏见!

答案 1 :(得分:1)

我一时想不起来了,但是有一种使用 JS 的方法,基本上是通过鼠标单击来删除轮廓。我是一年前做的,我只是对细节一头雾水。