Element 是一套基于 Vue 的桌面端组件库,于 2016 年 9 月开源,目前已经成长为 Vue 社区最受欢迎的开源项目之一。不久前我们发布了它的 2.0 版本,在这个版本中,除了新增功能外,我们还着重提升了各个组件的可访问性。今天就为大家做一个介绍。
tabindex
键盘可访问性要求页面上的所有可交互组件均可通过键盘操作,且应尽量与系统自带组件的操作习惯保持一致。在实践的过程中,主要用到的知识点就是 tabindex 。什么是 tabindex 呢?
在 web 页面中,我们把用户按下 Tab 键可到达的元素列表称为 tab 队列。HTML 中默认只有 a、button 和 form 元素包含在 Tab 队列中(不同浏览器可能会有些差异)。如果想把其他元素添加至 Tab 队列,就需要通过 设置 tabindex 来实现了。tabindex 可以设为多种值:
具体实现
接下来我们按照残障用户通过键盘或者辅助设备使用页面的步骤,结合 Element 中的一些组件,详细讲解如何为组件提升键盘可访问性。
到达组件
在 HTML中 disabled 的 input 元素会被移出 tab 序列且不可聚焦。移除 disabled 元素的可聚焦性有利有弊,利在于可以减少键盘操作的复杂性,弊在于对于一些依靠 move focus 来阅读屏幕的用户,disabled 元素相当于被隐藏了。因此需要根据具体的场景具体分析,但是不管如何选择,建议整个系统保持一致。
Element 组件选择的是将 disabled 元素移除可聚焦性,也就是说在组件内进行焦点管理时,disabled 元素不会被计算进来。比如,对于可选择的 Tree 组件,若某个树节点被禁用了,那么它是不包含在焦点管理中的。
在 Element 中,每个组件有且仅有一个可聚焦元素出现在 Tab 列表中。具体哪个元素被包含在 Tab 列表,获得初始化焦点,可以视情况而定:可以是最后一次焦点离开时的焦点元素,也可以是组件中被选中的第一个元素。
对于 Tree 组件,默认情况下,我们为第一个树节点设置了 tabindex = 0,即通过 Tab 键会导航至第一个树节点;而对于可选择的 Tree (即每个树节点前有一个 checkbox 框,供用户选择),我们则为第一个被选中的树节点设置了 tabindex = 0。
在组件内切换元素
焦点进入组件内部后,用户可以使用方向键在组件内可聚焦元素之间导航,此时需要进行组件内焦点管理,具体的实现是通过监听组件内的 keydown 事件,根据 keyCode 的值完成焦点转移;
焦点管理应当遵循以下原则:
*:foucs { outline: 0 none; }
焦点管理有以下两种方法,各有利弊,视情况选择。比如 Element 的 Tree 组件选择的是下面第一种方式,而Autocomplete 组件选择的是第二种,两种组件的不同选择是基于最初组件的实现方式来衡量的:
1、给焦点初始元素设置 tabindex = 0, 其他的可聚焦元素设置属性 tabindex = -1
2、当在组件内按下方向键时,设置下一个元素的 tabindex = 0, 其他元素 tabindex = -1;然后执行element.focus()
3、用户按下 Tab 键,焦点准备离开组件时,如果设计要求下一次组件重聚焦时,焦点元素为某个特定元素的话,则设置该元素 tabindex = 0,其他元素 tabindex = -1
使用 tabIndex 管理焦点的一个好处是,浏览器会把当前 focus 元素滚动到 view 区域。
操作组件内元素
当用户定位到想要操作的元素时,接下来就是操作元素,如点击、选中等。我们应当尽可能地为用户的键盘操作提供便利。我们通过以下几方面进行介绍:
focus 就像鼠标的 hover,意味着当前元素可能被选中,也可能不被选中;而 selected 表示当前元素是已选择状态。一个组件内的子元素可以被 focus,也可以被 selected,甚至可以两种状态共存,所以要注意区分两种状态的视觉效果。
在 Element 中,我们对 RadioGroup 组件进行了处理,让它的 selected 状态跟随 focus,即:随着焦点的移动,元素也将被选择,通过可聚焦元素的 focus 和 blur 事件来触发元素的 selectd 状态。但是有些情况下,这对可访问性也是有害的,有时元素被选择时会引起页面刷新、跳转或者发起请求等超出用户预知的行为,如 Tabs 面板切换伴随 Ajax 请求等,就不适合将两种状态进行绑定。
此外,可选择的 Tree 组件也不适合将两种状态绑定。我们的做法是,当树节点获得焦点时,通过监听 keydown 事件,判断 keyCode 值为 space/enter 键时,才触发它的 selectd 状态。
为 hover、click、mousedown 等鼠标事件提供相应的 focus 、blur、keydown 事件。比如 Tree 组件的树节点 click 事件可由 keydown 监听 space/enter 键来触发。
在满足基本的键盘操作之后,适当地为组件添加快捷键能够有效地提高用户的操作效率,如通过 Esc 键用来关闭对话框和弹层,通过 space/enter 键用来触发元素的 click 事件等。设置快捷键时应注意以下几点:
注意事项
结语
目前 Element 只是实现了大部分组件的键盘可操作性,还有很多不足之处,如 focus 状态的视觉样式不统一,以及快捷键设置需要后续进一步优化等。欢迎各位开发者围观指导,不吝赐教。
本项目地址:https://github.com/ElemeFE/element