焦点管理和惰性

Avatar of Eric Bailey
Eric Bailey on

DigitalOcean 为您的旅程的每个阶段提供云产品。 立即开始使用 $200 免费积分!

许多辅助技术的形式使用键盘导航来理解和对屏幕内容采取行动。 一种导航方式是通过 Tab 键。 如果你使用它来快速在表单上从一个输入跳到另一个输入,而无需使用鼠标或触控板,你可能已经熟悉这种导航方式了。

Tab 将按照它们在 DOM 中出现的顺序跳转到交互式元素。 这是为什么源代码的顺序与设计的视觉层次结构相匹配如此重要的原因之一。

可获得焦点的 交互式元素 列表是

交互式元素在以下情况下获得焦点

  • 它已通过 Tab 键导航到,
  • 它被点击,在链接到另一个可获得焦点的元素的锚点之后,
  • 或者焦点通过 element.focus() 在 JavaScript 中以编程方式设置。

焦点类似于用鼠标光标悬停在元素上,因为您正在标识要激活的元素。 也是 为什么视觉上明显的焦点样式如此重要

焦点指示灯在首页线框图中移动。 它从徽标开始,移动到产品,然后是服务,然后是职业、博客、联系,最后停在一个“了解更多”按钮上。

焦点管理

焦点管理是指协调哪些元素可以接收焦点事件,哪些元素不能接收焦点事件的做法。 这是前端开发中比较棘手的方面之一,但对于提高网站和 Web 应用的无障碍性至关重要。

焦点管理的最佳实践

99% 的情况下,您都希望保持焦点顺序不变。 我再怎么强调这一点也不为过。

只要您使用 <button> 元素作为按钮、使用锚点元素作为链接、使用 <input> 元素作为用户输入等等,焦点就会自行运作,无需任何额外操作。

在极少数情况下,您可能希望将焦点应用到超出焦点顺序的元素,或使通常无法接收焦点事件的元素可获得焦点。 以下是一些关于如何以无障碍且直观的导航方式进行操作的指导原则

操作:了解 tabindex 属性

tabindex 允许元素获得焦点。 它接受一个整数作为值。 它的行为会根据使用的整数而有所不同。

不要:将 tabindex="0" 应用到不需要它的元素

可以接收键盘焦点的交互式元素(如 <button> 元素)不需要应用 tabindex 属性。

此外,您不需要在非交互式元素上声明 tabindex 来确保它们可以被辅助技术读取(事实上,如果不存在角色和可访问名称,这将是 WCAG 的失败)。 这样做实际上会为使用辅助技术的人 创建一个意外且难以导航的体验 — 他们有其他预期的方式来读取此内容。

✅ 操作:使用 tabindex="-1" 进行 JavaScript 焦点设置

tabindex="-1" 用于使用 JavaScript 创建可访问的交互式小部件。

声明 tabindex="-1" 将使元素通过 JavaScript 或点击/轻触获得焦点。 但是,它不会让元素通过 Tab 键进行导航。

❌ 不要:使用正整数作为 tabindex

这是一种严重的反模式。 使用正整数将覆盖预期的选项卡顺序,并为尝试导航内容的人创建一个混乱且令人迷失的体验。

这种情况发生一次就足够糟糕了。 多次声明就完全是噩梦。 认真说:不要这样做。

❌ 不要:创建手动焦点顺序

交互式元素仅凭其使用就可以被选项卡选中。 您不需要在一系列交互式元素上设置一系列具有递增值的 tabindex 属性,以便按照您认为人们应该在您的网站上使用的顺序进行导航。 相反,您可以让 DOM 中元素的顺序来完成此操作。

焦点捕获

可能有些时候您需要阻止元素获得焦点。 一个很好的例子是 焦点捕获,它是指有条件地将焦点事件限制在元素及其子元素的范围内的行为。

焦点捕获不要与 键盘陷阱(有时称为焦点陷阱)混淆。 键盘陷阱是指使用键盘导航的人无法从某个小部件或组件中退出,因为存在糟糕的循环逻辑。

您可以使用焦点捕获的一个实际示例是模态窗口

焦点指示灯在首页线框图中移动,并打开一个模态窗口来演示焦点捕获。 模态窗口内部是模态窗口容器的选项卡停止点,一个视频播放按钮、一个取消按钮、一个购买按钮和一个关闭按钮。 模态窗口关闭后,焦点将返回到触发模态窗口的按钮。

为什么这很重要?

将焦点保持在模态窗口内可以传达其边界,并帮助告知哪些是模态内容,哪些不是模态内容 — 这类似于视力正常的人如何看到模态窗口“漂浮”在其他网站或 Web 应用内容之上。 如果以下情况,这将是一个重要的信息:

  • 视力低下或完全失明,并依赖屏幕阅读器来帮助传达交互模式的转变。
  • 您视力低下,使用放大显示器,在这种情况下,模态窗口边界外的焦点可能会令人困惑且令人迷失。
  • 您完全通过键盘进行导航,否则可能会从模态窗口中退出,并在尝试回到模态窗口时迷失在底层页面或视图中。

怎么做?

可靠地管理焦点是一件复杂的事情。 您需要使用 JavaScript 来

  1. 确定当前页面或视图上所有可获得焦点元素的容器元素。
  2. 确定被捕获内容的边界,包括第一个和最后一个可获得焦点的项目。
  3. 从被确定为可获得焦点的元素中删除交互性和可发现性,这些元素不在被捕获内容集中。
  4. 将焦点移动到被捕获的内容中。
  5. 监听信号表明要关闭被捕获内容的事件(保存、取消、关闭/点击Esc键等)。
  6. 当被相关事件触发时,关闭被捕获的内容区域。
  7. 恢复之前移除的交互性。
  8. 将焦点移回触发被捕获内容的交互元素。

为什么我们要这样做?

我不会说谎:这一切都很棘手,也很耗时。然而,焦点管理和合理的、可用的焦点顺序是一个Web 内容无障碍指南。它非常重要,以至于被认为是关于可用性的国际法律约束标准的一部分。

可Tab键操作且可发现

移除可发现性和交互性的方法有一些技巧。

屏幕阅读器具有交互模式,允许它们通过虚拟光标探索页面或视图。虚拟光标还允许使用屏幕阅读器的人发现页面中不可交互的部分(标题、列表等)。与使用Tab和焦点样式不同,虚拟光标仅供使用屏幕阅读器的人使用。

当您管理焦点时,您可能希望限制虚拟光标发现内容的能力。对于我们的模态示例,这意味着阻止用户在阅读模态时意外地“跳出”模态的边界。

可发现性可以通过明智地使用aria-hidden="true"来抑制。但是,交互性则更微妙一些。

进入inert

inert 属性是一个全局 HTML 属性,它将使移除和恢复交互元素的可发现性和焦点能力变得容易得多。以下是一个关于它如何工作的示例

<body>
  <div 
    aria-labelledby="modal-title"
    class="c-modal" 
    id="modal" 
    role="dialog" 
    tabindex="-1">
    <div role="document">
      <h2 id="modal-title">Save changes?</h2>
      <p>The changes you have made will be lost if you do not save them.<p>
      <button type="button">Save</button>
      <button type="button">Discard</button>
    </div>
  </div>
  <main inert>
    <!-- ... -->
  </main>
</body>

我故意避免在模态中使用<dialog>元素,因为它存在许多辅助技术支持问题

inert已在保存确认模态后的<main>元素上声明。这意味着<main>中包含的所有内容都无法接收焦点,也无法点击。

焦点被限制在模态内部。当模态被关闭时,可以从<main>元素中移除inert。这种处理焦点捕获的方法比现有技术要容易得多。

请记住: 关闭事件可以由模态示例中的两个按钮引起,也可以由按下键盘上的Esc键引起。一些模态还允许您点击模态区域之外来关闭。

对 inert 的支持

最新版本的Edge、Chrome 和 Opera 都支持inert,当启用了实验性 Web 平台功能时。Firefox 支持也即将发布!唯一例外是 Safari 的桌面版和移动版。

我很希望看到 Apple 为inert实施原生支持。虽然提供了一个 polyfill,但它对所有主要屏幕阅读器都有非微不足道的支持问题。不太好!

此外,我想提请注意来自inert polyfill 项目的 README中的这条注释

与原生inert实现相比,polyfill 在性能方面会很昂贵,因为它需要大量的树遍历。

树遍历意味着 polyfill 中的 JavaScript 可能需要大量计算能力才能工作,因此会降低最终用户的体验。

对于低功耗设备,如廉价的 Android 智能手机、旧笔记本电脑以及执行计算密集型任务(如运行多个 Electron 应用程序)的更强大的设备,这可能意味着会发生冻结或崩溃。原生浏览器支持意味着这种行为对设备的负担要轻得多,因为它可以访问 JavaScript 无法访问的浏览器部分。

Safari

就我个人而言,我对 Apple 缺乏对inert的支持感到失望。虽然我知道为浏览器添加新功能是一项非常复杂且困难的工作,但inert似乎是 Apple 应该更早支持的功能。

macOS 和 iOS 从历史上看对无障碍功能的支持一直很好,并且辅助技术友好功能是其营销活动中的一个常见部分。支持inert似乎是 Apple 使命的一个自然延伸,因为该功能本身会为简化可访问的 Web 体验的开发做出巨大贡献。

令人沮丧的是,Apple 对其正在开发的内容以及我们何时可以大体上预期看到它保持缄默。因此,inert的未来是一个开放性问题。

Igalia

Igalia是一家致力于浏览器功能的公司。他们目前正在进行一项实验,公众可以投票选择他们希望看到哪些功能。这项举措背后的原因超出了本文的范围,但您可以在Smashing Magazine 上阅读更多相关内容

Igalia 正在考虑的一个功能是为 WebKit 添加对inert的支持。如果您一直在寻找一种改善网络无障碍功能的方法,但一直不确定如何开始,我鼓励您认捐。5 美元、10 美元、25 美元。无需太多,每一份捐款都有意义。

不幸的是,inert没有赢得开放优先级实验。这意味着我们仍然不知道 Apple 是否正在开发它,或者何时可以预期它出现在Safari 技术预览版中。

iOS 15.4 将在禁用的inert属性支持下发布。这是一个好消息,因为它表明 Apple 正在开发它。

总结

管理焦点需要一些技巧和细心,但非常值得这样做。inert属性可以极大地简化这一过程。

inert这样的技术也代表了 Web 平台最强大的优势之一:能够为新出现的行为铺平道路,并将其编纂成易于使用且有效的东西。

进一步阅读


感谢Adrian RoselliSarah Higley 的反馈。