Accessibility guide for developers/zh
无障碍对我们的用户而言是很重要的功能。通过考虑一些基本的想法和规则,我们可以改进页面的无障碍功能。 实现无障碍功能是困难的。因为没有固定的和普遍接受的技术标准来适用于所有用户。 本页面并未列出或讨论MediaWiki中特定的无障碍功能问题。 它试图重注在技术选择和「该做」与「不该做」上,以防止出现无障碍问题。
就开发方面来说,我觉得这应该成为我们的规则手册:
如何实现无障碍
有一些重要的概念你应该牢记于心。
衡量无障碍功能的多种方式
无障碍功能涉及很多方面,请考虑以下几点:
- 事情应该变得易于理解:无论从文字、视觉、逻辑层面,还是就其复杂程度而言。
- 部分用户交互时需要屏幕阅读器,不过,使用诸如放大镜、高对比度模式、文本朗读引擎、自定义样式表(CSS)以及特殊键盘或输入设备的情况也同样普遍,甚至可能更常见。
- 应确保其易于触达;考量因素包括响应速度、价格可承受度、地理位置便利性、语言支持、硬件兼容性等。
总之,无障碍功能不仅仅是键盘无障碍,也不仅仅是屏幕阅读器无障碍。 之所以我们通常重点提及这两者,是因为它们以往很容易被忽视。 但是这些问题也是可以解决的,并且它们往往为实现其他任何类型的改进提供了基础。
一些无障碍问题往往是产品设计、战略选择、目标受众等方面的问题。 要将这些方面的情况总结为通用于MediaWiki生态的规则难度较大,因此本文不作探讨。
键盘导航
我们称之为键盘导航,但它的真正含义是:不要依赖指示设备(触控、鼠标)。
- 所谓键盘导航,就是通过键盘控制焦点并执行相应的动作。
- 可以通过 Tab 键访问的元素都是可聚焦的,但并非所有可聚焦的元素都能通过 Tab 键访问。
- 凡是鼠标能做到的事情,都应当能通过键盘做到。
- 键盘导航信息可被屏幕阅读器用于增强用户体验。
屏幕阅读器
- 屏幕阅读器会使用一种特殊的“光标”,这种光标通常按照 DOM 的逻辑结构进行导航。
- 焦点通常会随屏幕阅读器光标移动,屏幕阅读器光标也常随焦点而动,但两者是不同的。
- 屏幕阅读器使用“无障碍功能”API,你可以将其视为在普通 DOM 之上提供的一个输入/输出“视图”。
- ARIA 是对 DOM 的标注,用于提升或调整 DOM 结构转化为无障碍功能 API 的方式。 请注意,它不能取代编写符合规范的 HTML 和 JavaScript。 要实现键盘导航,仅仅需要遵循逻辑 DOM 顺序即可! 关于 ARIA 的更多信息,请参阅 w3.org 的解释 和 MDN 的解释。
- 屏幕阅读器并不仅仅局限于通过逻辑 DOM 结构进行导航,这只是默认的方式。
- 比如,屏幕阅读器可以读取鼠标指向的内容。
- iOS 上的 VoiceOver(旁白)采用一个屏幕光标,通过在触摸屏上的拇指定位和手势进行操控。
- 多数屏幕阅读器软件拥有额外的导航模式,例如可以在页面内按地标区域、自动生成的内容目录,甚至用户定义的“书签”进行罗列和导航。
- 由上述罗列出来的多种导航方法,可知: (屏幕阅读器导航)既有线性的起点和终点,也支持非线性的左、右、上、下浏览。 在构建页面时,不宜过度认为用户会使用这些特定的导航模式,但同样不应完全否定这些模式存在的意义。 不要将用户的视觉能力与屏幕阅读器能够向用户传达的空间感知相混淆。 例如:
- [image]上图展示了... Still acceptable
- [image][image]左边的图片展示了...右边的图片展示了... Still acceptable
- [image][image]右边的图片展示了...左边的图片展示了... Not acceptable
- [image]上图展示了... Not acceptable
- [image][image][image]左边的图片展示了...右边的图片展示了... Not acceptable
- [image][image]一些完全不同的东西。左边的图片展示了...右边的图片展示了... Definitely not acceptable
开发指南
围绕无障碍功能的开发存在着多种标准,说实话,几乎所有这些标准,尽管看起来能很好地发现问题,但在提供技术方案时仍存在非常显著的问题(往往需要大量“蹩脚的折衷方案”)。 这引起了社区中大量的争议。 比如说,我们应该辨认出那些没有什么争议性的东西,那些简单来说我们永远该(或永远不该)做的东西以及背后的原因。 如果我们把这些没有什么争议性的东西从那些有争议的东西中分隔出来,实现一些特定的目标就会变得容易非常多。
确保始终使用或提供
- 恰当的语义化 HTML 元素
- 按照 HTML 元素的设计目的去使用它们。 例如:
- 绑定点击处理器时,建议使用
<button>
,而非<div>
、<span>
或<a>
- 如果你觉得某个地方需要加粗显示,请思考使用标题或
strong
元素是否会更恰当
- 绑定点击处理器时,建议使用
- 有逻辑的标题结构
- 所有的页面都应该总是有自己的逻辑,以及具有连贯性的标题结构。 标题对屏幕阅读器的用户而言是一种基础的导航工具。
- 标题级别(如 H1、H2 等)的嵌套不应跳跃层级。 (换句话说,不要出现 H2->H4。)
- 标题应该具有描述性
- 同一级别的标题内容应当是独一无二的。 (在同一个 H2 区域下,不应出现两个同为 H3 级别且内容相同的标题。)
- 导航与主要内容之间应有所分隔
- 图片的
alt
属性应提供有意义(或描述性)的值。 - 对于装饰性图片,alt 属性应使用空值(即 alt="");更推荐的方式是,用 CSS 背景图片代替。
- 通常情况下,图片的 alt 属性优先级高于图像的 title 属性,甚至高于包裹该图片的链接的 title 属性。
- 为链接设置
title
属性 - 该属性的值通常显示为鼠标悬停时的工具提示。
- 只有当 title 属性的内容与链接文字不同时,才应使用 title 属性。
- 多数情况下,屏幕阅读器并不会朗读链接的 title 属性,除非该阅读器已通过明确设置来执行此操作。
lang
、dir
与hreflang
属性- 正确使用
lang
和hreflang
属性,可以在屏幕阅读器中实现恰当的语音选择,并在浏览器中启用正确的拼写校正等功能。
- 足够的对比度
- 务必始终检查你的颜色是否有足够的对比度 对于文字内容,小号字体需要更高的对比度(这是由于抗锯齿造成的)。
- 键盘导航焦点的指示
- 务必 不要 移除焦点,除非你为
:focus
状态设定了自己的焦点指示样式。- 否则,不要进行
outline: 0
(指移除默认焦点指示)。 - 当定义任何伪类(例如
:hover
或:active
)的样式时,也应该为:focus
状态定义相应的样式。
- 否则,不要进行
- 键盘导航
- 网页上的交互元素必须能够通过键盘进行操作。 请务必确认浏览器设置允许通过 Tab 键进行导航,且不使用鼠标等指向设备也能控制所有交互元素。
- 对于默认不支持键盘访问的元素(即非
<a>
,<area>
,<button>
,<input>
,<object>
,<select>
,<textarea>
类元素),使用tabIndex: 0
使其能够通过键盘访问。- 此时,还应添加一个监听 keydown 事件的处理函数,用于响应 Enter 键 (keyCode 13) 和 Space 键 (keyCode 32)。
- 利用
tabindex: -1
,使元素不对屏幕阅读器可见。(例如,对那些在一个<li>...</li>
内部,仅作为视觉标签的链接使用) - 默认通过键盘可访问的元素,会将 Enter 键或 Space 键的按下行为传递给 click 事件处理器。
- 对于默认不支持键盘访问的元素(即非
- 对话框等组件
在无障碍功能处理不当的情况下,对话框往往是对屏幕阅读器和键盘用户而言最难以访问的元素之一。 请务必在这上面投入一些精力。
- 用于开启对话框的元素,应设置
aria-haspopup
。 - 对话框本身也应该设置为
role=[dialog | alertdialog | tooltip]
- 在 DOM 结构中,对话框应被插入到恰当的位置;[1] 或 aria owns/controls 需要指明开启对话框的元素与对话框之间的关系。
- 在打开对话框时,应记录打开前获得焦点的元素,并将焦点移到对话框内的第一个可通过 Tab 键获取焦点的元素。
- 在模态对话框开启时,请务必确保无法操作页面其他部分。
- 对话框区域外的点击应被捕获并处理:可以忽略这些点击,或让它们关闭对话框。
- 确保焦点不会通过 Tab 键转移到对话框外部的链接或表单元素。
- 借助 aria-hidden 属性,确保屏幕阅读器无法访问对话框外部的元素。
- 确保对话框有关闭功能(支持按 Esc 键关闭,且包含一个可通过 Tab 键聚焦并带有描述性文本的关闭按钮)。
- 当对话框关闭时,应将(键盘)焦点返回到打开对话框前存储的焦点位置。 如果你没有将对话框按 DOM 顺序插入,则需要指定对话框的正确 所有者,以便屏幕阅读器能回到同一点。
- 推荐阅读:Aria modals, Aria modal dialog, ARIA nonmodal dialog, ARIA tooltips。
不应该做的事
- There is common advice to use
left: -1000px
to push something (often the labels of icon buttons) out of the viewport for visual users and still have it in the accessibility DOM.text-indent: -9999px
is variant of this. This is BAD advice.- This breaks our RTL rendering in several browsers. Specifically in rtl mode it creates a large canvas left of the viewport and scrollbars, much as +1000px would create in ltr mode. (If needed,
top: -1000px
is preferred overleft: -1000px
to avoid this). - VoiceOver on mobile is unable to use this text as a fallback, since it is a 'positional' screen reader. You cannot move your finger over this text and thus the text will not be read either. (aria-label is often the better choice).
- Lastly, this enlarges the render surface needed to calculate the final webpage and this can impact performance on mobile devices.
- Insightful overview of 'hide text offscreen' tricks are given by Jonathan Snook.
- This breaks our RTL rendering in several browsers. Specifically in rtl mode it creates a large canvas left of the viewport and scrollbars, much as +1000px would create in ltr mode. (If needed,
- Things should not be repeated often. If you have a 100 links on a page that can open a dialog, then don't add 100 labels to those 100 links telling the user that it can be used to open a dialog. Telling a user how to use/what to do with the interface is a good thing, doing it consistently is simply annoying. Find a different way to explain it once (an
aria-live=polite
might be an idea in this case ?). <a href="#">Hide</a>
with an onclick handler. VO reads such JS as "internal link Hide". Use a proper button, or<a role="button" tabindex="0">Hide</a>
, with 'Space' and 'Enter' key handlers in the onclick. But no href attribute.- Do not nest interactive functionality inside another interactive element (links or buttons inside links). This confuses screen readers.
避免
- Unicode symbols
- Most assistive technologies are not good with symbols. Therefore, try to avoid characters such as ↑, → or more complex characters, because many screen reader won't understand them. If they are required, try to wrap with a span element with the title attribute, so that the title attribute can communicate the implicit meaning within the context to the reader.
- Small fonts
- Legibility is preferred. If you make something so small that it is hard to read, do you even need it to begin with? Also avoid small fonts with low or mediocre contrast values (even if they fall inside the WCAG guidelines, small sizes require more explicit contrast then large sizes, especially with anti aliasing enabled).
- Unusually large fonts
- If you make text much larger than normal, it can become similarly hard to read (unless it's very short). This applies mostly to body text, or anything that takes up more than a couple lines. But the larger the text is, the more lines it will take up.
- tabIndex > 0
- DOM order is preferred wherever possible. DOM order provides context for the actions.
- Workaround
- Traditionally, accomplishing 'full' accessibility has required a lot of workarounds for html itself, the browsers and even specific screenreader software. However these workarounds often come with side effects, make use of bugs or unspecified behavior and inevitably create technical debt.
- MediaWiki, because of the users it seeks to serve, the amount of code, it's (lack) of funding, etc tends to prefer future proof code over code that easily breaks. As such it generally avoids workarounds even if that might sometimes limit the accessibility we can deliver. Decisions on this are often influenced by the relative audience of the feature in MediaWiki. If something is ubiquitous for all users a workaround is more warrented than if the feature affected is only used by a tiny part of the audience (for instance, reading a page vs modifying the configuration of the installation).
考虑
- ARIA Roles
- If a div or span behaves like an actual button use
role="button"
. alsorole="dialog"
androle="alert"
- Be careful with roles. For instance, don't add
role="button"
to a<th>
element, since the<th>
element has an implicitrole="columnheader"
, which will be overwritten. Instead use nested elements. Similarly for<li>
which has an implicitrole="listitem"
- If a button creates a popupdialog, use
aria-haspopup
. - Use
aria-labelled-by
for contexts where this is not fully logical by itself (so everywhere except for labels in forms and headers in tables).
- If a div or span behaves like an actual button use
- Avoid tables for layout purposes and test on smaller screen widths.
- hide stuff: https://www.tpgi.com/html5-accessibility-chops-hidden-and-aria-hidden/
- skip/jump to links
參見
- Wikimedia Design Style Guide: Accessibility principles
- Open bugs and feature requests related to the accessibility in MediaWiki and other Wikimedia software
- W3C Web Accessibility Initiative: Tips for Getting Started
- W3C Web Accessibility Initiative: Web Accessibility Evaluation Tools List
- Firefox Developer Tools: Accessibility Inspector
- Chrome Developer Tools: Accessibility features
- Accessibility and usability cleanup
- Blogposts
- Software
- WAVE, a Web accessibility evaluation tool
- Accessibility simulation on MediaWiki. Experience a page as a color blind person would experience it.
- https://www.deque.com/axe/ browser extension for accessibility auditing a page
- https://www.powermapper.com/products/sortsite/checks/accessibility-checks/ webapp for accessibility auditing. See also https://www.powermapper.com/tests/
- University of Cambridge - Impairment simulator software (Microsoft Windows only)
- Guides by 3rd parties
- Designing accessible services by UK Home Office
- Inclusive Design by Microsoft