【译】开发无障碍的Web组件

WBOY
Release: 2016-06-21 08:47:36
Original
1474 people have browsed it

原文: http://www.zcfy.cc/article/320

这篇文章的审校工作是由Mallory van Achterberg完成的。谢谢所有SitePointer的审校者,因为你们,SitePointer才能提供如此优质的内容。

在 上一篇文章 中,我演示了如何创建一个有多选功能的Web组件。读者在评论区域提到了Web组件无障碍这个重要的话题。毋庸置疑地,如今Web无障碍非常重要。所以,让我们来看看无障碍的含义,以及如何提高Web组件的可访问性(通过一个真实的例子)。

本文中的代码示例将基于上一篇文章中的代码。你可以从 GitHub仓库 复制一份,也可以查看本文结尾的 例子 。

提高Web组件可访问性的必要条件

组件的可访问性通常涉及以下方面:

  1. 标签语义化
  2. 键盘支持
  3. 视觉无障碍

让我们更深入地了解各个方面。

标签语义化

你应该听说过屏幕阅读器。屏幕阅读器通过大声播放屏幕上展示的内容,帮助盲人或弱视群体使用应用。现在有很多屏幕阅读器,例如Windows的 NVDA 和 JAWS ,Chrome的 ChromeVox ,以及OS X的 VoiceOver 。

当元素获得焦点时,屏幕阅读器会将该元素的相关信息朗读给用户听。因此,当浏览器的焦点落到 时,用户能通过视频阅读器了解到他们正在应对一个文本输入框(可以输入内容的东东)。但如果焦点落到了一个空的

上,那么屏幕阅读器不会报道任何信息。

为了解决这个问题,我们可以参考 WAI-ARIA (Web无障碍标准计划 - 无障碍富互联网应用),通过添加特殊的ARIA属性提高组件标签的语义化。这些额外语法能帮助阅读器分辨界面上的属性、关系和状态。ARIA的详细使用说明可以在 WAI-ARIA开发实践 找到。

键盘支持

我们对键盘支持的目标是可以完全通过键盘使用组件。WAI-ARIA为 许多UI控件 定义了行为和键盘交互方式。如果想知道组件应支持什么按键,可在文档中寻找并参考类似组件。例如,多选组件与 组合框 类似。

除了支持键盘操作,我们还应主动提示用户如何使用按键操作组件(例如,在应用中提供指引)。

视觉无障碍

这里会介绍组件的视觉无障碍问题。请保证你能对以下问题回答“是”:

  • 所有元素和文字都足够大,能被看清楚吗?
  • 组件在高对比模式下是否能清晰传达信息?
  • 若组件没有颜色,是否能被正常使用?

记住,并不是所有有视力障碍的用户都 完全看不见 。有相当一部分用户是弱视或色盲。

提高多选Web组件的可访问性

现在,我们将通过前面提到的方法,提高多选组件的可访问性。以下是具体的步骤:

  • 扩展标签语义
  • 添加键盘支持
  • 验证视觉可访问性

别忘了,你可以在文章的底部查看组件示例,或者通过 GitHub仓库 下载代码。

所有的代码片段都可以通过 multiselect.html 获取

扩展标签语法

经验表明,我们最好优先使用原生HTML元素,而不是自定义组件。如果你可以使用内置无障碍功能的原生HTML控件,那么就尽量使用它。万不得已时,再自定义组件并使用ARIA属性。 在HTML页面中使用WAI-AIRA避免冗余 中有更详细的说明。

在这个例子中,多选组件是一个自定义组件,因此,我们需要使用ARIA属性。首先,让我们在 ARIA文档 中找到类似的组件。貌似多选组件与复合框组件比较相似。那么,根据 复合框描述 ,看看我们需要添加哪些ARIA属性。

根据指引,我们需要添加以下角色:

  1. role="combobox" 组件的根元素
  2. role="listbox" 选项列表
  3. role="option" 下拉列表中的每一项

需要添加的ARIA状态属性:

  1. aria-expanded="true/false" 为根元素添加该状态,以表明组件是打开还是关闭状态
  2. aria-selected="true/false" 为下拉列表的每一项添加该状态,以表明选项是否被选中

我们可以直接将 combobox 和 listbox 角色添加到组件的标签中:

<div class="multiselect" role="combobox">  <div class="multiselect-field"></div>  <div class="multiselect-popup">    <ul class="multiselect-list" role="listbox">      <content select="li"></content>    </ul>  </div></div>
Copy after login

为了给每个选项添加 option 角色,我们需要在 refreshItems 方法中遍历选项。当组件被创建时,这个方法会被调用。

multiselectPrototype.render = function() {  this.attachHandlers();  this.refreshField();  this.refreshItems();};multiselectPrototype.refreshItems = function() {  var itemElements = this.itemElements();  for(var i = 0; i < itemElements.length; i++) {    var itemElement = itemElements[i];    // set role and aria-selected property of an item    itemElement.setAttribute("role", "option");    itemElement.setAttribute("aria-selected", itemElement.hasAttribute("selected"));  }};multiselectPrototype.itemElements = function() {  return this.querySelectorAll("li");};
Copy after login

我们可以在 togglePopup 方法中为控件添加 aria-expanded 属性。该属性决定了显示还是隐藏该列表。

multiselectPrototype.togglePopup = function(show) {  this._isOpened = show;  this._popup.style.display = show ? "block" : "none";  // set aria-expanded property  this._control.setAttribute("aria-expanded", show);};
Copy after login

我们还要根据每个选项的 selected 属性初始化它们的 aria-selected 属性。 aria-selected 属性用于表示选项的选中状态。我们可以通过 selectItem 方法和 unselectItem 方法更新该状态。

multiselectPrototype.selectItem = function(item) {  if(!item.hasAttribute("selected")) {    // set aria-selected property of selected item    item.setAttribute("aria-selected", true);    item.setAttribute("selected", "selected");    this.fireChangeEvent();    this.refreshField();  }  this.close();};multiselectPrototype.unselectItem = function(item) {  // set aria-selected property of unselected item  item.setAttribute("aria-selected", false);  item.removeAttribute("selected");  this.fireChangeEvent();  this.refreshField();};
Copy after login

ARIA属性添加好了。下一步是支持键盘操作。

添加键盘支持

打开 标准文档 ,阅读 Keyboard Interaction 部分,看看我们需要支持哪些操作。

以下是使用键盘操作多选框需要的基本按键:

Alt + Up/Down ArrowEscUp/Down ArrowEnterBackspace
Copy after login

使组件可聚焦

支持键盘操作第一步是支持聚焦到组件。我们需要设置 tabindex 属性来完成这一步,该属性的行为依赖于它的值:

  • 正的属性值定义了聚焦组件的顺序
  • 0 - 该元素获得焦点的顺序由浏览器决定
  • -1 - 用户无法通过键盘选中该元素,但开发者可通过使用Javascript的 focus() 方法选中它

自定义组件的 tabindex 应该为 -1 或 0 ,因为我们无法知道元素在页面上的获得焦点的顺序。因此,我们将多选组件的 tabindex 设为了 0 。

<div class="multiselect-field" tabindex="0" aria-readonly="true"></div>
Copy after login

下一步是处理 keydown 事件:

multiselectPrototype.attachHandlers = function() {  this._control.addEventListener("keydown", this.keyDownHandler.bind(this));  ...};
Copy after login

keyDownHandler 根据 event.which ,调用特定的按键处理函数。

multiselectPrototype.keyDownHandler = function(event) {  switch(event.which) {    case 8:  // Backspace      this.handleBackspaceKey();      break;    case 13: // Enter      this.handleEnterKey();      break;    case 27: // Escape      this.handleEscapeKey();      break;    case 38: // Up Arrow      event.altKey ? this.handleAltArrowUpKey() : this.handleArrowUpKey();      break;    case 40: // Down Arrow      event.altKey ? this.handleAltArrowDownKey() : this.handleArrowDownKey();      break;    default:      return;  }  // prevent native browser key handling  event.preventDefault();};
Copy after login

一旦用户按下按键,我们便通过 event.preventDefault() 阻止默认行为。

使用键盘打开/关闭下拉框

用户可通过 Alt + Down Arrow 组合按键打开多选框,通过 Alt + Up Arrow 和 Esc 关闭多选框:

multiselectPrototype.handleAltArrowDownKey = function() {  this.open();};multiselectPrototype.handleAltArrowUpKey = function() {  this.close();};multiselectPrototype.handleEscapeKey = function() {  this.close();};
Copy after login

open 和 close 方法会调用 togglePopup :

multiselectPrototype.open = function() {  this.togglePopup(true);};multiselectPrototype.close = function() {  this.togglePopup(false);};
Copy after login

通过键盘浏览选项

首先,将每个选项的 tabindex 都设为 -1 ,这样我们便可以聚焦到它们。

multiselectPrototype.refreshItems = function() {  var itemElements = this.itemElements();  for(var i = 0; i < itemElements.length; i++) {    var itemElement = itemElements[i];    ...    // 设置选项的tabindex属性    itemElement.setAttribute("tabindex", -1);  }  // 初始化聚焦选项的索引  this._focusedItemIndex = 0;};
Copy after login

_focusedItemIndex 属性保存了聚焦的选项的索引。

用户可通过 Up Arrow 和 Down Arrow 浏览选项。代码可通过刷新当前聚焦选项索引来实现浏览功能。

multiselectPrototype.handleArrowDownKey = function() {  this._focusedItemIndex = (this._focusedItemIndex < this.itemElements().length - 1)      ? this._focusedItemIndex + 1   // go to the next item      : 0;                           // go to the first item  this.refreshFocusedItem();};
Copy after login

当用户在列表底部按下 Down Arrow 时,阅读器会聚焦到第一个选项。

当用户在列表顶部按下 Up Arrow 时,阅读器会聚焦到最后一个选项。

multiselectPrototype.handleArrowUpKey = function() {  this._focusedItemIndex = (this._focusedItemIndex > 0)    ? this._focusedItemIndex - 1        // go to the previous item    : this.itemElements().length - 1;   // go to the last item  this.refreshFocusedItem();};
Copy after login

refreshFocusedItem 方法会聚焦到索引为 _focusedItemIndex 的选项:

multiselectPrototype.refreshFocusedItem = function() {  this.itemElements()[this._focusedItemIndex].focus();};
Copy after login

最后,我们需要修改 open 和 close 方法。使得当多选框被打开时,阅读器会自动聚焦到 _focusedItemIndex 对应的选项,当多选框被关闭时,阅读器会聚焦到多选框容器。

multiselectPrototype.open = function() {  this.togglePopup(true);  this.refreshFocusedItem();};multiselectPrototype.close = function() {  this.togglePopup(false);  this._field.focus();};
Copy after login

现在我们可通过添加CSS,使得聚焦的选项看起来更突出:

::content li:focus {  outline: dotted 1px #333;  background: #efefef;}
Copy after login

通过键盘选中/取消选中选项

用户可通过 Enter 按键选中当前聚焦的选项。如果多选框为打开状态,我们可以获得聚焦的选项,并通过 selectItem 方法选中它。

multiselectPrototype.handleEnterKey = function() {  if(this._isOpened) {    var focusedItem = this.itemElements()[this._focusedItemIndex];    this.selectItem(focusedItem);  }};
Copy after login

用户可通过 Esc 取消最近一次的选择。如果当前有被选中的选项,我们可以通过 unselectItem 方法取消最近一次的选择。

multiselectPrototype.handleBackspaceKey = function() {  var selectedItemElements = this.querySelectorAll("li[selected]");  if(selectedItemElements.length) {    this.unselectItem(selectedItemElements[selectedItemElements.length - 1]);  }};
Copy after login

现在我们支持了所有必要的键盘操作,因此用户可完全通过键盘操作组件。

视觉无障碍

组件尺寸

多选框使用了相对单位 em ,它的大小依赖于容器的字体大小。因此,组件的字体大小是灵活的,如果有必要,我们可以轻松的增大字体。

高对比度模式

弱视或有其它视觉障碍的用户有时会使用高对比度模式。OSX系统的用户可在设置中启用高对比度模式,Windows系统也提供了 高对比度主题 。除此之外,Chrome的扩展 High Contrast 也支持用户在浏览器中使用高对比度颜色。

一起来看看组件在高对比度模式的样子:

它看着还行,但是有一个问题:被选中的选项与其它选项看着区别不大。因此,我们可以稍微调整被选中的选项的颜色,来解决这个问题。

没有颜色

颜色无障碍是视觉无障碍的一个重要方面。互联网圈子中有许多用户是色盲。因此,我们不应完全依赖于颜色来传达重要信息。我们可以在灰度模式中检查组件(通常操作系统或某些软件都会提供这个功能)。由于多选组件本身就是灰色的,因此我们可以跳过这一步。

示例

经过以上的优化,这里是最终的代码:

Multiselect Web Component by SitePoint ( @SitePoint ) on CodePen .

总结

为了提高组件的可访问性,我们应该确保一下几点:

  • 标签语义化,这样屏幕阅读器等辅助工具才能帮助用户使用组件。尽量使用原生的HTML控件,如果必须自定义控件,请添加有意义的ARIA属性。

  • 可以完全通过键盘操作组件。通过 tabindex 使组件可被聚焦。参考ARIA实践指南实现键盘交互。

  • 组件在高对比度模式和无色模式下也要能正常显示。

感谢你的阅读。欢迎大家评论,分享在web组件可访问性方面的经验。

标签: accessibility , keyboard accessibility , multiselect component , polymer , web components , X-Tag

英文原文: https://www.sitepoint.com/accessible-web-components/?utm_source=html5weekly&utm_medium=email

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template