原文:http://www.zcfy.cc/article/607
随着我们建立的网站逐渐变得更像 app,web 平台也需要跟上,提供给开发者所需的创建高可访问性用户体验的工具,这一点很重要。
最近,我遇到两个场景,在这两个场景下我添加合适的键盘支持到我所创建的组件上是极其困难的。在经过很多实验和研究之后,我比较清晰地意识到可能在 web 平台上缺少了一些原语,如果有这些原语,我的工作将会变得简单一些。我将会解释这两个场景,并涵盖一些关于如何解决这两个问题的思路。
模态窗口是一个出现在页面上的对话框,通常用一个遮罩层遮住它背后的内容。如果一个模态窗口正在被展现,用户不应该能操作网页上的任何其他东西。
如果你曾经试图使模态窗口具备好的可访问性,那你应该知道即使它们看起来很无害,模态窗口实际上是终结 web 可访问性的大 boss。它们会把你吃掉,吐出骨头来。例如,一个合适的模态窗将需要有以下特点:
键盘焦点应该要被移动到模态窗口中,并且当窗口关闭时恢复到之前获得焦点的元素。
键盘焦点应该被限制在模态窗口中,从而用户不会意外敲 tab 键把焦点移出模态窗口。
读屏软件应该也被限制在模态窗口中,以避免意外离开模态窗口。
做到以上三点可以说是相当困难的,需要大量的 aria-hidden
组合变换来限制读屏软件,并且还需要管理焦点切换来限制 TAB
。这里有一个我能找到的最好的例子。请注意这个例子假设你的模态窗口是与你的 main content 同级的 dom,这样你可以简单将 aria-hidden
应用于 main 元素。然而,如果你的模态窗口混合在你的 main content 中(可能是因为定位的原因),那么真的有点难搞了,你需要想一个办法将 aria-hidden
应用到 main content 中的每个元素,除了你的模态窗口(或者它的父容器)。这肯定比预想的要难。
<dialog>
怎么样?HTML 规范提出了使用 <dialog>
元素的思路,这将神奇地解决上面所有的问题。问题是到目前为止只有 Chrome 已经实现了它,而其他浏览器厂商看起来无动于衷。此外,<dialog>
可能不是正确的解决方案。让我们考虑另一个例子:
侧边栏菜单是一个在响应式网站非常流行的 UI 模式。但是是否侧边栏菜单与 <dialog>
一样?侧边栏菜单也需要遵守上面列出的三个要点,然而若把它也称为一个 dialog 那也实在有点太随便了。我的预感是当创建一个侧边栏菜单时,许多开发者可能不认为它是 <dialog>
。
blockingElements
(阻塞元素)与其用扭曲 <dialog>
的语义来达到我们的目的,不如暴露一个 JavaScript API 来给我们同样神奇的东西。这样我们可以创建我们自己的自定义元素并利用这个 API 来得到我们想要的。这个想法已经在 whatwb/html GitHub 仓库上讨论过了,它的讨论内容在 "Expose a stack of blocking elements"
设想的 API 看起来如下:
// put element at the top of the blocking elements stack
document.blockingElements.push(element);
document.blockingElements.pop();
// see https://github.com/whatwg/html/issues/897#issuecomment-198565716
document.blockingElements.remove(element);
document.blockingElements.top; // or .current or .peek()
将一个元素放到 blockingElements 堆栈的顶部实际上意味着页面上的其他一切被无效化(因此没有了键盘焦点和屏幕阅读器离开模态窗口的风险)。而当一个元素被从堆栈中 pop 掉,焦点自然地回到前一个被聚焦的元素上。这使我们能够解释 <dialog>
的行为,于是组件作者可以使用它来创建任何他们想要的效果,这与可扩展的 web 运动的宗旨相吻合。这么做的一个自然的副产物是我们额外获得了一大堆可访问性特性。开发者不需要在页面上到处写 aria-hidden
属性或者写键盘限制,替代地,他们可以使用最好的 API 来创建一个 dialog 并且好的可访问性将自然产生。这是一个彻底的胜利。
目前 blockingElements
仍然是一个新的想法,而新想法是脆弱的,因此请克制在 GitHub issue 里吐槽、打口水仗的冲动
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8