技术有温,代码有爱: 如何让互动能说话?

发布于 大漠

特别声明,本文主要由我和我的同事 @光驰 一起完成!

马老师在达沃斯论坛说:

人是暖的,我们必须让技术暖起来!

在互动团队的同学都知道,我们团队有一个明确的愿景: 人人可开发,处处有互动  。其实我想说,除了 人人可开发,处处有互动 还应该让 互动有温度,让互动能说话 。

去年双11的 PK盖楼 上过头条,火爆全网,我想今年双11主互动项目: 超级星秀猫 也将会再次燃爆全网。记得去年我和大家一起聊了聊如何构建 有温度的互动 ,让30万视障人士可以很好的在天猫双11“剁手”“盖楼”分红包:

image.png

说实话,看到这样的消息,作为主导互动无障碍优化的我来说, 无比的自豪,无比的幸福 !今年我将和我们团队的 @光驰 同学和大家一起聊聊:“ 如何通过技术,让互动能说话 ”。

借此机会,我要特别感谢双11项目组的所有同学,参与互动无障碍的建设,感谢你们给予我的强大支持。没有你们的努力和支持,我们不能让互动有温度,也不能让互动能说话。

先来体验一下会说话的互动

或许你会感到好奇,能说话的互动是什么样的?为此,大家可以浏览一下下面这个视频,先体验一下能说话的互动是什么?

如果观看视频体感不强的话,我更建议你戴上眼罩,开启手机的屏幕阅读功能(iOS是“VoiceOver”,Android是“TalkBack”),并且尝试着是否可以根据屏幕阅读器的指示来撸猫,收喵币,做任务,分享等一系列的操作。只有进入到这样的世界,你才能更好的体验到能说话的互动真正的意义。

如果你对这两款应用不是很熟悉的话,建议你花一点点时间阅读:

嗯,这就是 技术的温度,代码有爱 。但话又说回来,在这个领域的探讨不仅仅是我们团队,在业内很多人都在不断的努力,都希望自己的产品能更好的服务更多的人群。比如:

特别是苹果、Google、微软、Adobe、IBM等公司在这方面做得尤其的好,并且都有专业的人员专业的团队不断在提高自己产品的可访问性。

不应该主动就放弃属于我们的一些用户

我们应该为自己感到庆幸的是,每天都可以享受着快乐而又美好的生活。比如说,每天一起床,就能睁开眼睛看到清晨赐给我们的第一缕阳光;每天都能大口大口呼吸着新鲜空气;甚至在你起床的第一刻还能听到小鸟那动人的歌声。

每天你都可以快乐的工作,幸福生活!

可你有没有想过,这些看似普通而又平凡的生活对于有些人来说是极其奢侈的,渴望的:

我一直在哭,一直在哭,哭我没有新鞋子穿。直到有一天,我发现有人没有脚...... —— @海伦·凯勒

当我们沉浸在 超级星秀猫 给我们带来的快乐之时,好像从未想到过这个世界有很多的人却什么都看不到;当我们沉浸在互动中配上“喵喵喵”的音乐带来的魔性的,好像从未想到过这个世界有很多的人一点声音也听不到;当我们沉浸在实现酷炫动效的成就感时,好像从未想到过这个世界有很多的人会因为这些动效带来不适,甚至发病。

我曾经完全不敢相信双目失明的人可以和正常人一样使用手机和电脑,和正常人一样聊天打字,能通过手淘购物,能通过饿了么点外卖,直到有一天在微博上看到有盲人在吐槽在手淘上购物不爽时...... 直到有一天我了解了盲人编程和聋哑程序员还有视障工程师时,我才知道在Web的世界中还有可访问性,无障碍设计这么一说。

世界好大,大到我们根本无法用语言来恰当地描述每一个存在着的事物。

据公开数据统计,全球有超过 10亿 人(占世界人口 15% )患有某种形式残疾。其中,色盲患者中,平均12名男性中就有一例,200名女性中就有一例,他们可能难以区分红色和绿色,或者黄色和蓝色。弱视患者30名人群中就有一例,他们没有任何的角膜,尽管能看到东西的大致轮廓,却难以阅读印刷文字,在法律上会被视为盲人。

中国有 2亿多 的障碍群体,其中包括 1700 万视障者 , 2000 万听力障碍者 , 7000 万读写障碍者 , 1.5 亿 65 岁以上的老年人 等等,加上其他各种类型障碍人群,这些 障碍人士加起来占中国人口总数 20% 以上 。

上面的数据还不包括那些临时性有障碍的人员,比如手臂、眼睛、耳朵因为意外受伤,造成临时性的障碍。

我们一直在提:“ 用户第一”, 那么他们是我们的用户吗?我觉得没有任何理由可以回答不是,如果说非要找一个理由,那应该就是一些连我们自己都没有意识到的意识被我们的潜意识选择了遗忘吧。

往大了一点说:

互联网是平等的,每个人都应该享有平等访问互联网的权利! —— @蒂姆伯纳斯-李

往小一点说:

无障碍是一种生活方式,也是一种我们都应该培养的文化!

对于Web开发者而言:

具有可访问性的Web对于每个人来说都是伟大的!

可访问性 vs. 包容性

一直以来,很多人都误认为: 可访问性(无障碍设计)就是为残障人士服务的 ,甚至一度的认为: 可访问性(无障碍)设计就是为盲人服务的 。事实上呢?并非如此。因为 有障碍 指的并不是残疾,应该把问题放到场景中来考虑:

image.png

我们可以把有障碍分成:

  • 永久性的 :指的是天生或后天由于各种原因,身体上有残疾的,比如聋哑、色盲、自闭症、阅读障碍和理解障碍
  • 临时性的 :指的是由于意外造成身体上临时性的障碍,比如手臂骨折、眼睛受伤和听力受伤等
  • 情景性的 :指的是在一些特殊场景下造成,比如在嘈杂环境引起听力下降,太阳等下造成阅读困难,多重任务时手无法腾出来做其他事情
  • 基础设施障碍 :指的是基础设施引起的障碍,比如说带宽低引起的连通性慢

想象一下下图这些场景:

image.png

基于这一点,我们在设计和开发我们的应用时,就应该考虑到: 更具包容性,更具多元化。但有一点,我们需要知道:

可访问性不等于残障人士;包容性同样也不等于可访问性!

就拿我们生活中的两个场景来做对比:

image.png

如果仅仅从Web的世界中来考虑的话:

  • 可访问性 :指的是建立一个有障碍人士也能访问的Web应用
  • 包容性 :指的是建立一个最大范围人群能访问的Web应用

对于可访问性是什么?我们后面会来介绍,但对于包容性是什么,这里就不做过多的阐述。这里推荐 Google 无障碍设计师 @夏冰莹 老师的关于“包容性设计” 的相关教程。

@夏冰莹 老师是这样描述 包容性设计(Inclusive Design)无障碍设计(Accessible Design) 和 **通用性设计(Universal Design)**的:

  • 包容性设计(Inclusive Design)是最广义的、让产品可以被不同用户(包括不同身体能力、语言、文化、性别、年龄、性取向等)使用的追求。
  • 无障碍设计(Accessible Design)针对身体能力差异,特指做出对残障使用场景(包括健全人会遇到的临时性与情境性残障)友善的设计。在国内,「无障碍设计」很好地对应技术界的「信息无障碍」概念。
  • 通用性设计(Universal Design)往往代表同一个设计可以被所有人使用,而包容性设计与无障碍设计并不强调解决方案只有一个,而是可以对不同人群有不同方案。通用性设计这个词近些年在互联网业界用得越来越少了(更多用于建筑/城市规划)。

理解概念总是费神的。我的感觉就是这样。把大家从包容性设计拉回来,我们继续回到可访问性上来。

WebAIM的2019年对排名 前100万 的网站和新增的 10万 多个内部网站进行了主页可访问性评估,并根据相应的检测出了一份有关于可访问性相关的报告。我摘出几个关键数据:

  • 100万 个主页中,发现了 60,909,278 个明显的可访问性错误,平均每个页面有 60.9 个错误
  • 98.1% 的主页存在 WCAG 2 故障

看到这个数据,你是不是会觉得不可能。那么在这里给Web开发者提一个问题,“自己开发的Web页面或应用有多少是具有可访问性的?”,如果不好回答,那说明上面的数据并不让人感到害怕。

A11Y是什么?

image.png

A11Y 是 “Accessibility” 的简写,也就是我们所说的Web可访问性,也被称为 Web无障碍 。

W3C-WAI是这样对A11Y定义的

Web accessibility means that people with disabilities can use the Web.

Web可访问性是指 让身心障碍者能够使用该Web服务的程度,亦即身心障碍者多容使用你的Web服务。相对于W3C的描述,我个人更喜欢维基百科对A11Y的定义

Web accessibility refers to the inclusive practice of removing barriers that prevent interaction with, or access to websites, by people with disabilities. When sites are correctly designed, developed and edited, all users have equal access to information and functionality.

旨于确保任何人都有办法获取放在网页上的媒体内容——无论人们是否遭遇了身体、心理或技术上的障碍,都不会妨碍人们接收作者所发布的信息。也就是让网上的内容“易于亲近”,易于获取、利用。比如说:

  • 有些看不太清楚字的人会使用屏幕放大器来阅读文字
  • 有些什么都看不见的人会使用盲文显示器来阅读文字
  • 有些色盲患者会使用一些高对比模式来获得更好地体验
  • 一些听力不太好的人在看视频的时候会选择带有字幕的视频
  • ......

正如前面提到过的,你可以尝试着: 你可以戴上眼罩,去感受如何在网上购物,订餐,玩游戏等等 。即, 用另一种方式去感受你曾经可以看到的东西。其实只要你用心去发现,这些都在诠释着“无障碍”(可访问书生 ) 。

为什么要做Web可访问性(A11Y)?

很多时候,很多同学会问:

  • 为什么要做Web可访问性 ?
  • 有障碍的用户数据占比并不多,为什么花时间刻意去做Web无障碍?
  • 做无障碍能给业务带来什么变化?

一直以来,大家都在提,技术需要为业务服务的。也基于这个原因,在做Web可访问性的时候,总是会和利益结合起来,花多少人力,用多少成本,给业务带来什么样变,有没有增长。或者说,Web可访问性在数字时代,给我们带来的ROI是多少?

这个问题对我来说有点难,我回答不清楚,但这个问题在社区中也有相应的讨论,我想下面文章中提到的一些观点应该能给你一些启发或答案:

就我个人而言,最早在手淘互动项目中做A11Y,我是抱着一种简单地想法:“ 我想让一些身心有障碍的人士也能参与互动项目”。如果说得高雅一点,就是 攻城狮 的一种情怀:

善解人意,考虑不同用户群体需求,显示您的关心!

试问自己,“给自己的产品(Web页面或Web应用)提供可访问性,难道不是我们(工程师)最基本的要求之一”?

当然,站在更高的角度去看问题,也可以把做Web可访问性的意义说得更大一些:

提升你的品牌声誉;扩大市场范围;降低法律风险;承担一定社会责任!

不管是基于什么原因去做Web可访问性,最终的目的都是: **让每个人都享有平等访问互联网的权利。**这也是 我们应该去培养的文化

让更多的人参与到Web可访问性的建设中来,让更多的人可以使用我们提供的服务。

A11Y的标准和原则

凡事都有自己的标准和原则,A11Y也是如此!

A11Y 依赖几个相互联系的部分,包括:

  • Web内容 : 指网站中的任意部分,如文本、图片、表单和多媒体,以及所有标记代码、脚本、应用,等等
  • 用户代理 : 软件,用户通过它来访问Web内容,包括桌面图形界面浏览器、语音浏览器、手机浏览器、多媒体播放器、插件及一些辅助浏览技术
  • 辅助技术 : 软件或服务,用户使用它产生Web内容,包括代码编辑器、文档转换工具、内容管理系统、博客、数据库脚本,以及其他工具

这些部分相互关联并相互支持。例如, Web内容 需要包含图像的文本替代。 这些信息需要 web浏览器 处理同时被 辅助技术转换, 例如读屏软件。 为了创建文本替代,作者需要创作工具 来做这些工作。

标准在为每个组件定义无障碍需求方面扮演着重要的角色。一些无障碍需求很容易满足,但是了解有障碍的人士如何使用Web的基本知识有助于更有效地实现这些需求。无障碍的某些方面需要更多的技术技能,也需要关于人们如何使用Web的高级知识。在所有情况下,在整个web项目中早期让用户参与将使您的工作更好、更容易。

W3C的Web无障碍推进(WAI)提供了一组被国际公认为Web无障碍标准指南。

image.png

还有一个用于 无障碍富网络应用(WAI-ARIA)的WAI规范,其中包括使用Ajax、JavaScript和相关Web技术开发的动态内容和高级用户界面控件。

其中, WCAG 是Web开发者构建A11Y的指南,它是目前Web无障碍的国际标准,合规等级分为三级( A 、 AA  和 AAA )。总的来说,该规范都围绕了四个原则:

image.png

可感知、可操作、可理解 和 强健(健壮)也被称为是构建A11Y的四大原则。

可感知信息和用户界面

可感知:信息及使用者界面应以使用者能察觉之方式呈现,使用者一定要能察觉呈现出来的信息。即,信息不能对使用者所有的感官均无形。

如果需要满足该原则,在Web开发时,我们就需要:

  • 用文本替代非文本内容
  • 内容有多种呈现形式
  • 内容的看和听更容易

比如,给Web中的媒体提供可替代的文本信息

  • 对图片(图标、按钮和图形)的简短描述;
  • 图表、示意图和插图上数据的说明;
  • 对音频和视频文件等非文本内容的简短说明;
  • 表单控件、输入框等用户交互组件的标注。

对于视力正常的用户而言,Web图像可以很以很好的向用户提供正确的信息,但对于一些视弱或完全失去视力的用户而言,他只能依赖其他的用户代理来使用Web,那么仅视觉呈现是无法向该群体传递所需信息。这个时候,替代文本就变得很重要:

  • 替代文本传达图片或功能的意图,提供等价的用户体验。比如,对搜索按钮的替代文本应该是“搜索”,而不是“放大镜”
  • 替代文本的展示方式有很多种。比如,对看不见屏幕或视力不好的读者可以大声朗读出来,可以增大文本字号,也可以在盲文设备上显示
  • 替代文本是控件和功能的标注,可以辅助键盘导航和语音识别导航(语音输入),也是识别音频、视频及其他格式文件乃至嵌入在网页中其他应用的标注

另外,为针对不同用户以不同的方式呈现,内容必须:

  • 正确地标记内容的结构,标题、列表、表格、输入字段,等等;
  • 信息或指令的顺序适应任何呈现方式;
  • 浏览器及辅助技术为定制不同的呈现方式提供便利。

满足这个要求的内容可以被正确的读出、放大,或者改编以适应不同人群的需求及偏好。比如,可以自定义使用不同颜色、字号或其他样式来呈现,以方便阅读。这个要求也有助于其他形式的适配,包括自动生成内容大纲和摘要,从而让用户了解梗概并聚焦到特定部分。

还有,在设计和内容中我们也要考虑一些注意事项,用于区分的内容。便于区分的内容更容易看和听,比如:

  • 不只使用颜色传达信息或标识内容;
  • 默认的前景和背景色有足够高的对比度;
  • 用户将文本放大到400%或增大文本间距时,内容不会丢失;
  • 用户放大文本或使用小屏幕时,文本可以重排;
  • 文本图片可以缩放或以实际文本替代,或尽可能避免使用;
  • 用户可以暂停、停止或调整音频的音量;
  • 背景音乐音量小且可以关闭,避免干扰和分神。

满足这个要求有助于将前景和背景分离,让重要的信息更突出。这一条也涉及不使用辅助技术的人群,而对使用辅助技术的用户,音量过大或对比度过高也会导致注意力分散。比如,很多色盲用户不会使用特殊工具,直接依赖网页提供足够的色彩对比度。

可操作的用户界面和导航

可操作:使用者界面及导览功能应具可操作性,使用者一定要能够操作界面。即,界面不能要求使用者无法执行的互动方式

按照下面这些要求去做,可以尽可能的让Web应用达到“可操作”诉求:

  • 可以通过键盘使用功能
  • 用户有允足时间阅读和使用内容
  • 内容不要诱发癫痫和物理反应
  • 用户可以方便地导航、找到内容并确认自己在哪里
  • 用户可以使用除键盘外的不同输入方式

简单地来看看怎么才能达到上面列的这几点。

再次要特别的声明: **给Web应用提供可访问性,绝不是说仅仅给盲人用户群体提供可访问性。**我们的应用群体可能在某个时间,某个地点让自己手臂受伤,造成临时性的障碍,他不得不使用键盘来操作,或者说有一群过度依赖键盘操作的用户群体使用我们构建的应用。这也就要求我们构建的Web应用需要为这些用户提供“ 使用键盘完全可以控制应用的能力”,比如:

  • 可以使用 Tab 正确导航到内容,
  • 可用 Enter 或 Space 键可以让得到焦点的链接跳转到指定地址
  • 可以通过键盘很好的控制表单控件,输入框及其他用户办面控件

也就是说,我们构建的Web应用应该:

  • 通过鼠标可以操控的功能,同样可以通过键盘实现;
  • 键盘焦点不会被内容的任意部分卡住;
  • 浏览器、创作工具及其他工具支持键盘操作。

满足这个要求能帮助键盘用户,包括使用人体工程学键盘、屏幕软键盘或开关装置的人方便上网。同样,对于使用语音识别(语音输入)来操作网页和通过键盘输入的人同样有帮助。

人与人是不同的,那么阅读理解同样的内容,有的人用的时间少,有的人用的时间多。比如,有些人打字慢,理解慢,操作控件不熟练,最终导致使用Web应用的速度慢。为此我们应该为这些用户提供足够的时间来阅读和使用。

所谓提供足够的时间,指的是:

  • 必要时提供解除、扩展和调整时间限制的机制;
  • 提供暂停、停止或隐藏移动、闪烁或滚动内容的机制;
  • 必要时延迟或避免打断用户;
  • 会话超时后重新认证确保不丢失数据。

现代Web上,动效的使用频率越来越高,特别是在互动项目中,动效的使用更是家常便饭。比如,跳动的图标,发光的按钮,飞跃的金币等。对于正常用户而言,这些动效可能让他们有着耳目一新的效果,对Web应用也有着锦上添加花的效果,但是这些动效对于一些用户群体的体验却是致命的。因为某种频率或图案的闪烁可能诱发光敏反应,包括癫痫。理想情况之下,应该完全避免内容闪烁,或者如果无法避免也要确保不会导致已知风险。

避免导致癫痫及物理反应的例子有:

  • 不使用某种频率或图案的闪烁;
  • 内容闪烁前对用户给出提示,同时提供替代方案;
  • 除非必要,要让用户可以关掉动画。

组织得当的内容可以让用户随时定位自己并有效导航,比如:

  • 页面标题表述适当,各部分标题也具有描述性;
  • 在一组网页中有多种方式可以找到相关页面;
  • 随时提醒用户在一组网页中的当前位置;
  • 让用户可以跳过多个网页中都有的内容块;
  • 键盘焦点可以看到,且焦点顺序有意义;
  • 链接的意图明确,理想情况下即使链接本身也能让人一目了然。

满足这个要求可以让用户根据自己的需求和偏好在多个页面间导航。比如:

  • 有人依赖层级导航结构如菜单来查找特定网页,也有人依赖网站的搜索功能
  • 有人可能用眼睛看,有人可能用耳朵听,而有人会同时看和听
  • 有人可能只使用鼠标,有人可能只使用键盘,而有人则会同时都用

除键盘之外的输入方式还有触摸激活、语音识别(语音输入)及手势,这些方式可以为很多人提供便利。但并非所有人都可以同样程度地使用所有方式。特别的设计考量可以最大化这些方式的优势,包括:

  • 要求敏捷及精确移动的手势有对应不需要高敏捷性的替代方式;
  • 经特别设计避免组件被意外激活,比如提供撤销功能;
  • 展示给用户的标注与代码中对象的名字对应,以支持通过语音激活;
  • 通过运动激活的功能也可以通过用户界面上的组件激活;
  • 按钮、链接和其他活动组件足够大,以便通过触摸来激活它们。

满足这个要求可以让更多有能力使用更多设备的人更方便地使用内容。这里的内容包括手机、笔记本电脑和售票机上的内容。

可理解的信息和用户界面

可理解:信息及使用者界面之操作应具可理解性,使用者一定要能够明白信息及使用者界面的操作。即,内容及操作皆不能超出使用者的理解能力。

我们应该尽可能的让Web应用满足以下几点,让应用达到可访问性的“可理解”原则:

  • 文本容易阅读和理解
  • 内容可以预测的方式出现和操作
  • 用户可以得到帮忙以避免和纠正错误

内容作者要确保文字具有可读性且大多数读者都比较容易理解,包括文字转语音读出来也一样。其中包括:

  • 标识网页使用的主要语言,如阿拉伯语、德语或韩语;
  • 标识文本、短语或网页中其他部分的语言;
  • 对不常见的词汇、短语、 习语和缩略语给出解释;
  • 尽可能用最简单明了的表达,或提供简化版本。

满足这个要求有助于软件包括辅助技术正确地处理文本内容。比如,软件因此可以正确地读出内容、生成页面摘要,并对不常用的技术词汇提供解释。同样,这也有助于人们理解复杂的句子、短语和词汇。特别是对具有不同认知背景的用户会有帮助。

很多人依赖可预测的用户界面,而不一致的外观和行为则会导致迷惑,转移用户注意力。要让内容可预测,可以:

  • 在多个页面相同位置重复出现导航条;
  • 给多个页面上重复出现的用户界面组件添加相同的标注信息;
  • 给没有用户同意不会发生的变化应用明显的区别。

满足这个要求可以让人们更快熟悉网站提供的功能和导航机制,并根据自己的特殊需求及偏好来使用网站。比如,有些人会给自己频繁使用的键盘导航功能定义快捷键。而也有人会记住在网站上到达某个特定页面或完成特定流程的步骤。这些都有赖于可预测及一致的功能。

表单及其他交互可能导致用户迷惑或难于使用,最终让用户犯错。帮助用户避免和纠正错误的做法包括:

  • 为用户提供说明、错误消息及建议,帮用户提供正确的信息;
  • 为复杂功能及交互提供上下文相关的帮助;
  • 必要时提供结果预览,以及纠正或重置表单的功能。

满足这个要求可以帮助因为看不到或听不到而难以理解潜在关联、顺序和其他提示的人。对于不理解功能,因此产生困惑或迷茫、记不住,或者因种种原因在使用表单和交互时出错的人同样也有帮助。

健壮的内容和可靠的解释

健性性:网页内容应可供身心障碍者以辅助工具读取,并具有相容性随着科技进步,使用者一定要能取用内。也就是说当科技及使用者代理演进后,内容仍应保有可用性。

健壮的内容兼容不同浏览器、辅助技术及其他用户代理。比如:

  • 确保标记是可以被可靠解释的,比如确保使用有效的标记;
  • 对非标准用户界面组件提供名称、角色和值。

满足这个要求可以最大化地兼容当前及未来的用户代理,包括辅助技术。特别地,这可以让辅助技术正确处理内容,以及通过不同方式呈现或操作内容。非标准(脚本化)按钮、输入字段及其他控件也包含在内。

是不是有一种感觉:

要让自己构建的Web应用满足可访问的四大原则,比登天还难

除了难之外,是不是还是有些不知所措,没关系。其实有很多检查清单可以帮助我们,比如:

这样我们就更容易知道我们的Web应用(或Web页面)存在些什么问题了。

至少我们可以做到这些

WebAIM的报告中列出了Web可访问性存在的几大问题

image.png

这些问题其实都没有达到构建A11Y四大原则中的某一条或某几条。比如:

  • 图片没有可替代文本,它就不符合“可感知”
  • 文本和背景颜色对比度不够,它也不符合“可感知”
  • 链接和按钮没有相应描述信息,可以说它们既然不符合“可感知”,也不符合“可操作”

在我们互动项目中,从 “天猫活力中心”、“金币小镇”、“618理想列车” 和 双11的“超级星秀猫” 四个项目做了无障缺陷相关的统计。四个项目中差不多 84 个缺陷的提交,这些缺陷主要有 焦点缺失 、 信息缺失 、 焦点混乱 、 焦点冗余 、 焦点穿透 、 角色缺失 、 朗读错误 和 控件关联 等。

image.png

上图展示的是: 焦点缺失 、 信息缺失 、 焦点冗余 、 信息错误 和 焦点穿透 等。

其实,在我自己做无障碍优化和指导团队同学做无障碍优化的过程,我发现Web开发者普遍都认为:

无障碍优化不是最重要的,放到最后来处理;也从不把无障碍优化当作基本功能和基本需求来做。

如果时间来不及就不了了之,如果没有人来做检测,也可能不了了之。

这或许就是造成Web无障碍缺陷最大的原因之下,甚至是对无障碍最大的误区:

把它当做成了产品的情怀功能,而非基础功能或者Bug去对待

另外,除了认知因素之外,很多Web开发者在无障碍优化方面的知识储备也是有一定的缺陷。比如:

  • 对A11Y不太理解
  • 对WCAG规范不太了解
  • 对A11Y检测缺失经验
  • 对HTML语义化标签理解不到
  • WAI-ARIA是万能的

这么说是有一定的理论依据的。我对平时碰到的问题做了一个简单的统计,在互动项目中无障碍优化中常见的缺陷主要有:

  • Web组件焦点冗余
  • 控件无焦点(比如按钮)
  • 元素没有正确的描述信息
  • 朗读冗余
  • 焦点顺序混乱
  • 焦点穿透

看上去似乎缺陷类型很多,处理起来麻烦,但是我们只需要平时在进行开发的时候,注意一些细节,这些问题就很容易的避开。

采用语义化标签

Web开发者都知道,构建一个Web应用或页面,一般由HTML,CSS 和 JavaScript组成,其中HTML是构建Web应用的骨架,有点类似于我们购买的毛坯房子,只有一些框框,没有使用CSS做一些美化处理。

就这个骨架,即 HTML。它对Web可访问性是非常重要的,因为一些用户代理或辅助技术(比如屏幕阅读器),他会根据HTML的语义标签向用户呈现相应的信息。也就是说,屏幕阅读器会根据你的标签,将正确的信息告诉用户。我们来看一个简单的示例,比如下面这样的卡片:

image.png

这样的卡片在我们的业务中是很常见的一种。不过我们在这只聊HTML。如果你拿到这个设计,你写HTML是不是像下面这样呢:

<div class="lists">
  <div class="item">
    <img src="path" />
    <div class="content">
      <div class="title">标题</div>
      <div class="des">描述</div>
    </div>
    <div class="button">按钮</div>
  </div>  
</div>  

我相信现在很多前端开发都是这么写的。

这样写其实对于一些辅助技术是不友好的,他只会向用户朗读相应的文本信息,并不能准确的向用户传达信息。

如我们来尝试着换更有语义的HTML之后的效果:

<ul>
  <li>
    <figure>
      <img src="https://img.alicdn.com/tfs/TB1ZV5ikSR26e4jSZFEXXbwuXXa-74-74.png" alt="主会场" />
      <figcaption>
        <h2>逛主会场景领喵币</h2>
        <p>最高可领1000喵币</p>
      </figcaption>
    </figure>
    <button>去逛逛</button>
  </li>
  <li>
    <figure>
      <img src="https://img.alicdn.com/tfs/TB1ZV5ikSR26e4jSZFEXXbwuXXa-74-74.png" alt="粑粑农场" />
      <figcaption>
        <h2>去粑粑农场施肥</h2>
        <p>最高可领1000喵币</p>
      </figcaption>
    </figure>
    <button>去施肥</button>
  </li>
</ul>

这个时候,屏幕阅读器向用户呈现的信息如下:

两个Demo对比下来,我想你已经看得出来语义化标签对于Web可访问性的重要性。

到目前为止,Web应用或页面不再只是HTML、CSS和JavaScript组成了,很多用户代理和辅助技术都在原有的基础上增加了 AOM 。即:

image.png

在一百多个HTML标签中,只有 div 和 span 是无语义的标签,但这两个标签也是众多Web开发都最喜欢使用的两个标签。在这里我建议大家平时构建Web应用的时候,不管是出于对技术的追求,还是为了更好的构建可访问性,我们都应该考虑使用更具语义化的标签。如果你对语义化标签使用存在困惑,你可以按下图这样的流程来选择:

image.png

HTML5也是一个庞大的知识体系,如果想彻底的了解清楚语义化标签的使用,还是需要阅读HTML规范,另外推荐大家几篇文章,或许对语义化标签的使用有所帮助:

正确构建文档大纲

Web页面的大纲很多时候是有HTML中的标题标签(<h1> ~ <h6>)来组建,文档大纲可以用来划分文档并使用这些划分创建具有清晰层次结构。如下图所示:

image.png

创建一个健全的文档大纲对于构建可访问性Web应用很重要。这是因为屏幕阅读器并不只是通过从上到下阅读页面上的内容,还有其他的导航方式,例如列出所有的标题,然后直接跳到一个特定的标题。换句话说,屏幕阅读器可以获得所有标题的列表,级别是用标题的文本来宣布的,以便用户更易于理解页面层次结构。

因此,我们在构建Web应用的时候应该正确的使用标题。WCAG 2.1为标题的可访问性提供了相应的指南:

  • A级标准:确保现有可见标题被正确使用,其级别反映了标题在标题层次结构中的相对顺序
  • AA级标准:确保标题的描述性文字的质量,而不是标题的存在
  • AAA级标准:确保网页的章节在被组织成章节时有标题

因此,如果我们只是想达到AA级别,已有的文本在视觉上充当标题的话,我们就应该使用正确的标题标签,并确保标题文本是描述性的。另外,在使用标题标签时,应该遵循两个基本原则:

  • 同一个页面只有一个<h1>
  • 不能在上升的过程中跳过一级

对于第一条规则很好理解,这里来解释一下第二条规则。

正如前面的截图所示,标题的层次是一级一级往下的,比如说,你要到达<h4>,就必须先从<h1><h2><h3>,不能直接从<h2>跳到<h4>。比如:

image.png

上图中橙色标注的都是原本缺少,确应该存在的标题,即标题有跳级现象,也就是违背了第二条规则。而且有的有多个<h1>标题,这也违背了原则一。

比如说,我们从<h1><h2><h3>再到<h4>这是正常的也是符合构建文档大纲的结构,但是,你可以从<h4>跳过<h3>直接跳到<h3>,如下图所示:

image.png

我一向提倡构建Web应用的时候,应该尽可能的使用具有语义化的标签元素。如果你因为某种元素未使用语义化标签又想让用户代理(比如屏幕阅读器)也能向用户呈现标题级别,那就需要使用ARIA中的role="heading"aria-level属性来声明:

<div role="heading" aria-level="1"></div> › <h1></h1> 
<div role="heading" aria-level="2"></div> › <h2></h2> 
<div role="heading" aria-level="3"></div> › <h3></h3> 
<div role="heading" aria-level="4"></div> › <h4></h4> 
<div role="heading" aria-level="5"></div> › <h5></h5> 
<div role="heading" aria-level="6"></div> › <h6></h6>

如果你想深入的了解文档大纲相关的内容,还可以阅读下面这些教程:

给图片提供替代文本

在互动的项目中,图像的使用是最频繁的,比如:

image.png

就上图来说,图片的用途就有多种,比如 氛围图 、 标题氛围图 以及 用户头像 和 等级示意图 。有些氛围图是只是装饰作用的,有的图是需要向用户传达信息的。不管是哪种图像,一般是采用HTML的 <img> 标签或CSS的 background-image 将图像运用到Web中。

对于视力正常的用户而言,看到图像就能了解你所要表达的信息,但对于视弱或者盲人而言,他是需要依赖一些辅助技术才能知道是图像,而图像的具体信息是需要通过 img 的 alt 属性的值来传达。也就是说,我们在使用 img 向用户表达信息时,一定要在 alt 设置上下文文本信息。

img 的alt设置值,可以参照下图这样的一个流程来进行:

image.png

注意,如果你使用一些无障碍方面的监测工具的话,在 <img> 元素上未显式设置 alt 属性,监测工具会给你抛出一个错误信息。

避免使用空链接或空按钮

首先这里所指的 空链接 和 空按钮 是指对应的标签内没有相应的文本信息,比如:

<a href="path"></a>
<button></button>

特别是一些图标链接或按钮,很多开发者习惯性的为其选择为空。同样拿任务面板举例吧:

image.png

任务面板中的每个任务都有一个“按钮”(也有可能是“链接”),从视觉上已经无法清楚的区分它是链接还是按钮了。

image.png

具体 它是按钮还是链接 不做具体争论。这里我们关注的是按钮或链接的文本信息。面板中任务的链接的文本信息是“去分享”、“去逛店”,“支施肥” 等。

当一个使用屏幕阅读器的盲人在链接上获得焦点时,没有合适的上下文,他们需要浏览和阅读周围的文本,或者在这种情况下,浏览到前面的标题,以确定这个“去分享”链接的上下文。如果这个模式在页面中重复多次,那么对于使用屏幕阅读器的用户来说就会变得非常沮丧。

要真正使链接(或按钮)可访问,我们需要在链接(或按钮)中默认提供上下文。最简单的方法是在<a>(或<button>)元素内添加描述链接(或按钮)的文本的上下文信息:

<a href="">去逛店<span class="sr-only">逛耐克旗舰店</span></a>
<button>去逛店 <span class="sr-only">逛耐克旗舰店</span></button>

虽然这是首选的方法,但是在某些情况下,这可能会在视觉上让人难以承受。在这种情况之下,可以简单地在.sr-only使用CSS,用于视觉上隐藏,但屏幕阅读器上不隐藏。

/* CSS */
.sr-only {
    border: 0 !important;
    clip: rect(1px, 1px, 1px, 1px) !important;
    clip-path: inset(50%) !important;
    height: 1px !important;
    margin: -1px !important;
    overflow: hidden !important;
    padding: 0 !important;
    position: absolute !important;
    width: 1px !important;
    white-space: nowrap !important;
}

.sr-only-focusable:focus,
.sr-only-focusable:active {
    clip: auto !important;
    clip-path: none !important;
    height: auto !important;
    margin: auto !important;
    overflow: visible !important;
    width: auto !important;
    white-space: normal !important;
}

示例中,在链接(或按钮)前面有标题,比如<h2>,我们还可以使用aria-labelledby属性将链接(或按钮)关联起来。当使用现有文本来构建上下文链接(或按钮)文本时,你将需要考虑措辞的质量。因此,我们可以像下面这样给链接(或按钮)添加相关联的上下文描述信息:

<ul>
  <li>
    <figure>
      <img src="https://img.alicdn.com/tfs/TB1ZV5ikSR26e4jSZFEXXbwuXXa-74-74.png" alt="主会场" />
      <figcaption>
        <h2 id="a11y__title--item1">逛主会场景领喵币</h2>
        <p>最高可领1000喵币</p>
      </figcaption>
    </figure>
    <button id="a11y__button--item1" aria-labelledby="a11y__button--item1 a11y__title--item1">去逛逛</button>
  </li>
</ul> 

给文档设置语言类型

为了确保正确的发音,屏幕阅读器为它们支持的每种语言使用不同的声音库。屏幕阅读器可以轻松地在这些语言库之间切换,但只有在Web页面指定为给定内容读取哪种语言的情况下才可以。

如果页面没有为 <html> 元素指定语言,那么屏幕阅读器就会假定页面使用用户在设置屏幕阅读器时选择的默认语言,这通常会导致无法理解内容。

比如说, <html> 未显式设置 lang 属性,Lighthouse 检测的时候就会抛出相应的错误信息:

image.png

曾经我就踩过这样的一个坑,在 <html> 没有设置 lang ,另外就是在中文Web页面设置了 lang 的值为 en ,结果iOS的“VoiceOver”朗读出来的信息是让用户听不懂,后来将 lang 的值设置为 zh-CN 才正常。

这个示例想提醒大家的是,在构建Web应用的时候,应该根据自己的应用设置正确的语言类型,比如中文简体,我们可以设置:

<html lang="zh-CN">
</html>  

表单控件缺少 <label>

在我们互动项目中很少会用到表单控件。但抛开互动项目而言,表单的使用是Web中的一个重点,那么表单无障碍设计的好与坏直接会影响用户是否能继续往下操作。比如登录、注册,比如购物下单,修改地址等。

在设计表单时,表单的控件除 type="button" 的 input 和带有 hidden 属性的 input 可以没有对应的 <label> 标签外,其他的表单控件都应该有一个对应的可读的标签( <label> )。

label之所以如此重要,是因为ATs(比如屏幕阅读器)技术使用它们来向用户展示所关注领域的目的。没有它,用户将无法理解他们应该在对应的input中输入什么。

此外,可以看到的label对其他用户也很有帮助,因为浏览器倾向于自动填充表单。这将隐藏字段中提供的标签,并让用户怀疑表单是否被正确地自动填充。标签总是比代表相同的图标更易理解。

对于复选框(<input type="checkbox">)和单选按钮(<input type="radio">),最好提供关于整个组的用途的信息,而不是单个选项。针对于该场景,可以使用<fieldset><legend>元素会更好些:

<fieldset>
    <legend>My favorite foods</legend>
    <label>
        <input type="checkbox" name="foods" value="pizza"> Pizza
    </label>
    <label>
        <input type="checkbox" name="foods" value="burger"> Burger
    </label>
    <label>
        <input type="checkbox" name="foods" value="pasta"> Pasta
    </label>
</fieldset>

在编写HTML时,<input>除了被<label>包裹起来之外,还可以通过labelforinputid来联动,比如:

<label for="firstname">First name:</label> 
<input type="text" id="firstname" />

如果使用WAI-ARIA,还可以通过label标签的idinputaria-labelledby联动,比如:

<label id="firstname">First name:</label> 
<input type="text" aria-labelledby="firstname" />

如果不能使用label时,可以使用aria-label或者在input上使用title(在input上不太使用title属性)。

使用 tabindex

HTML中有很多元素是可聚焦元素,比如 <a> 、 <button> 、 <input> 、 <select> 等。可聚焦元素可以让用户通过键盘的 Tab 让其获得焦点。 但是,很多Web开发者已经普通习惯了使用 <div> 和 <span> 之类的标签元素。

用一个简单地示例向大家展示使用 <button> (可聚焦元素)和 div (不可聚焦元素)在屏幕阅读中给用户呈现的差异:

<button class="button">去逛逛</button>

<div class="button">去分享</div>

具体差异可以看下面这个视频:

从上面的视频中可以发现,整个 <button> 元素有一个焦点,而 <div> 元素只有其文本(Text Node)才有焦点。

如果我们希望给不可聚焦元素也有焦点的话,就需要使用 tabindex 属性tabindex 属性有几个规则:

  • tabindex="-1" , Tab 键无法获取焦点,但JavaScript的 focus() 事件可获得焦点
  • tabindex="0" , 可以让非聚焦元素按自然顺序出现在 Tab 键序列中
  • tabindex="1" , 元素置于 Tab 序列最前,但不建议将 tabindex 的值设置为 1 或大于 0 的值

也就是说,如果你热衷于使用不可聚焦的元素,那就请不要忘记给该元素显式设置 tabindex 的值。比如上面的示例,我们在 div 元素上显式设置 tabindex 的值为 -1  或 0 ,iOS的“VoiceOver”都可以在整个元素上有焦点:

<button class="button">去逛逛</button>

<div class="button" tabindex="0" role="button">去分享</div>

<!-- 或 -->

<div class="button" tabindex="-1" role="button">去分享</div>

这个时候,iOS的“VoiceOver”给用户呈现的效果如下:

地标标签和地标角色

在WAI-ARIA中角色 role 的介绍中就有地标角色,即 Landmark ,他们和HTML5的 <main> 、 <header> 、 <nav> 、 <aside> 和 <footer> 有着相应的对应关系。

image.png

这允许我们给站点中的元素增加我们想要的语义属性。第一个主要区域便是用于为屏幕阅读器提供信息,以便用户可以找到常见的页面元素。

<header>
  <h1>标题</h1>
  <nav>
    <ul>
      <li>
        <a href="">CSS</a>
      </li>
      <li>
        <a href="">HTML</a>
      </li>
    </ul>
    <form>
      <label for="search">搜索</label>
      <input type="search" id="search" />
    </form>
  </nav>
</header>

<main>
  <article>
    <h2>文章标题</h2>
  </article>
  <aside>
    <h2>AD</h2>
  </aside>
</main>

<footer>
  <p>版本归属</p>
</footer>

“VoiceOver”呈现给用户的效果如下:

如果你转到VoiceOver的地标菜单(使用VoiceOver 绑定键(你可以在VoiceOver Utility 中设置) + U 访问,然后使用光标或者键盘来选择菜单选项),你将看到大部分元素都已很好地列出,因此可以快速访问它们。

image.png

尽管如此,我们可以做的更好。这个搜索表单是一个人们愿意找到的重要的地标,我们可以设置 input  的类别为 search  (<input type="search">)。 另外,在一些老的浏览器(尤其是IE8) 是无法识别的这些HTML5 的元素语义化的。

让我们来优化上文代码并且用上无障碍特性。首先我们给HTML 的结构加上角色。

<header role="banner">
  <h1>标题</h1>
  <nav role="navigation">
    <ul>
      <li>
        <a href="">CSS</a>
      </li>
      <li>
        <a href="">HTML</a>
      </li>
    </ul>
    <form role="search">
      <input type="search" name="search" placeholder="搜索查询" aria-label="通过网站内容进行搜索" />
    </form>
  </nav>
</header>

<main role="main">
  <article role="article">
    <h2>文章标题</h2>
  </article>
  <aside role="complementary">
    <h2>AD</h2>
  </aside>
</main>

<footer role="contentinfo">
  <p>版本归属</p>
</footer>

我们用了一个额外的功能: input 元素用了属性 aria-label, 它给它一个描述性标签,可以由屏幕阅读器读出,尽管我们没有 label  元素。在这些情况下,这非常有用——像这样的搜索表单是一个非常常见的,易于识别的功能,添加 label  会破坏页面设计。

再用VoiceOver时,呈现给用户的效果如下:

如果由于某种原因,你的网站仅使用 <div>  构建,那么你肯定很需要用 ARIA 角色以提供所需的语义!

ARIA有可能不是良药,他可能是毒药

社区中有一种声音,认为ARIA对Web可访问性是一种良药:

image.png

其实我更想说的是,虽然ARIA提供的角色、状态和属性在某些场景对Web可访问性是有所帮助的,但它不是万能的。如果用得不好或不对,那么ARIA对于依赖屏幕阅读器的用户而言是一种毒药。它不仅不能增强Web可访问性,反正会给用户带来更大的困惑和理解成本。

即使ARIA不会影响鼠标或键盘用户的行为。只有使用辅助技术的用户才能感知到使用了ARIA与否之间的差异。Web开发人员可以给任意HTML标签添加任意的ARIA。这样做虽然不会影响不使用辅助技术的用户,但对于使用辅助技术的用户而言,这将可能是致命:

NO ARIA is better than bad ARIA!

其实,很多时候ARIA不应该是用来构建可访问Web的焦点(意思是Web开发者不应该过度依赖ARIA来构建可访问性Web应用),特别是有了HTML5规范之后。因为HTML5解决了屏幕阅读器常常面临的许多语义问题。

而且其中最重要的是:

ARIA永远无法替代语义化HTML标签。

拿一个示例来解释这一点。比如现在很多依赖React,Vue等框架开发的同学,他们从不关注语义化的HTML标签,甚至是不知道怎么使用有语义化的标签。另外就是在移动端上开发,很多Web开发者不太喜欢使用原生的 <a> 、 <button> 标签之类的,就拿 <button> 来说吧,开发者不喜欢其默认的样式,但在Web中又离不开 <button> 的功能,就喜欢使用带有 role="button" 的 <div> 来替代 <button> ,可这样做, <div> 并不具备 <button> 默认的所有功能:

<button class="button">确认</button> 

<div role="button" class="button">确认<div>

image.png

对于 <button> 标签而言,它有一些内置的默认功能。开发者不需要做任何事情,屏幕阅读器就知道他是按钮。除些之外,对于依赖键盘操作的用户来说, <button> 也更友好,通过 Tab 键可以让 <button> 得到焦点,但 <div> 默认是没有的:

aria-3.gif

正如上图所示,用户按键盘的 Tab 键时,可以让 <button> 得到焦点,并且得到焦点时,有一个 :focus 状态的样式,显式告诉用户。如果要让像 <div> 这种非聚焦元素有焦点,需要显式设置 tabindex 。

<div> 标签上显式的使用 role="button" 可以让屏幕阅读器知道他是一个“按钮”,并且使用 tabindex="0" 可以使Tab让其获得焦点,但并不能修复“点击事件”。我们必须给其添加相应的事件,比如点击事件 click :

document.querySelector("div.button").addEventListener('keypress', e => { 
  if (e.code === 'Enter' || e.code === 'Space') { 
    alert('pressed!') 
  } 
})

aria-7.gif

在Web开发的时候,虽然HTML标签中有很多具有语义的标签,但在制作一些控件时,并不能很好的通知辅助技术。这个时候我们需要使用ARIA来增强这方面的能力。比如在这次双11星秀猫中,爆击猫猫会出不同的提示信息,这个时候就需要ARIA相关的特性:

但这并不意味着,ARIA在HTML中可以随时随地的使用,因为使用不当,会给辅助技术带来麻烦,会增加用户的理解成本。

ARIA应该在原生HTML标签失去语义或失败的地方使用,也就是说,当HTML(HTML5)元素没有可访问性支持时。

提供可见的焦点指示

在HTML中有很多元素被称为可聚焦元素,比如我们熟悉的<a><button><input><textarea><label>等:

a11y-developing-25.jpg

HTML中可聚焦元素最大的特点就是,它们是自动插入到Tab键顺序中,并内置了键盘事件处理,无需开发者进行干预。但并非所有元素都是可聚焦元素;在你按Tab键在页面上循环跳转时,段落(<p>)、<div>以及各种其他页面元素不会获得焦点,这是设计使然。一般不需要聚焦无法与用户进行交互的元素。

可聚焦元素另一个特点就是,可聚焦元素在获得焦点时都有可见的焦点指示器。就拿Chrome浏览器来说,获得焦点时样式上有明显的变化:

a11y-developing-26.png

可聚焦元素获得焦点时的指示器对于Web可访问性同样的很重要。因为焦点指示器可以帮助用户知道键盘的焦点正在哪个元素上。这里的关键是:

所有可聚焦元素(或组件)在被聚焦时都有一个可见的焦点指示器

“可见是一个相对的术语”,WCAG规范对这个可见焦点指示器也有明确的定义

文本字段中有明确的插入符;控件周围有明显的可见边框

比如下面这个示例

image.png

使用Tab键操作上面的Demo,你看到的效果会像下面这样:

同样的,在一些辅助技术(比如屏幕阅读器)上也有焦点指示器,只不过样式上看上去有所差异:

在CSS中,我们可以使用一些伪类选择器,比如:focus:focus-within:focus-visible给可聚焦元素设置焦点指示器样式:

a11y-developing-29.jpg

前面也提到过了,对于可聚焦元素,如果没有显式设置CSS样式,那么不同的浏览器对焦点指示器的样式也会有所差异。也基于这个原因,很多开发者粗暴的将焦点指示器的样式去掉了:

a11y-developing-30.png

*,
*:focus {
    outline: none 0;
}

加上很多视觉设计师在视觉上也很讨厌默认焦点指示器样式,但很多时候对焦点元素指示器样式没有做额外的设计。这样对于视力正常的用户来说并无大碍,但对于强度依赖于键盘或其辅助技术的用户就很不友好了,因为这些用户不知道自己正处于哪个位置。

因此,为了Web可访问性,我们不应该直接去掉焦点指示器样式效果,如果需要更好的看的指示器效果,可以使用CSS的outlineborderbox-shadow等属性来美化。另外,CSS的伪类选择器:focus:focus-within:focus-visible也有一定的差异性(对不同用户操作方式有差异)。不过这里不做详细阐述,如果感兴趣,还可以阅读下面这些教程:

添加足够的颜色对比度

a11y-developing-11.gif

颜色对比度是一个经常被忽视的问题(可访问性 ),从众多网站或应用程序的“无障碍”检测结果就可以发现“颜色对比度达不到WCAG标准”:

a11y-developing-12.png

视弱的人可能会发现,如果背景颜色和前景颜色对比度低,难于阅读。而且从世界卫生组织在一份关于视力障碍和失明统计报告中可以得知有近2.7亿人患有中度至重度视力障碍。因此在设计一个Web应用时,需要考虑文本和背景之间颜色要有充分的对比度。

根据WCAG视觉对比(WCAG Visual Contrast)规范,我们可以得知,文本与背景之间的颜色对比度应该至少是 4.5:1(可达到级别 AA)。如果文本更宽,更大和更重,那么对于视力有一定障碍的用户更便于阅读,那么颜色上的对比度就可以稍微更低一点。比如,文本字号是18pt14px粗体时,最低对比度可以下降到 3:1

a11y-developing-13.png

WCAG视觉对比(WCAG Visual Contrast)规范可以帮助视力障碍用户更好地使用互联网产品。

如果你实在拿不准配色是否合理(Web安全颜色),你可以借助在线工具,比如Contrast Checker:

a11y-developing-14.png

该工具是根据WCAG 2.0 guidelines for contrast accessibility标准来做的。比如下面图所展示的效果就是一个较好的效果:

a11y-developing-15.png

如果你想获得更详细的分数,我建议你使用WebAIM颜色对比度检查器,此工具将计算不同对比度的级别(AAAAAA)中常规文本大小和较大文本大小的分数,同时可以更改颜色值实时查看结果。

或者使用浏览器开发者工具也可以来检查和调整CSS:

a11y-developing-16.png

这里特别向大家推荐一款Chrome浏览器的插件VisBug,可以帮你对Web应用上的任意元素的颜色对比度进行检测。

令人感到惊讶的是,早在1992年就有人开始使用下图这样的公式来计算颜色的对比度:

a11y-developing-18.png

有关于该公式更详细的计算可以阅读《Signs and color contrast》一文。

别仅依赖颜色作为关键信息传递

a11y-developing-19.gif

当你的应用需要和用户做一些重要交流的时候(比如有单的填写),不要仅把颜色作为视觉提示。这是因为低视力,特别是色盲的用户很难理解。比如下图所示:

a11y-developing-20.png

上图左侧是正常用户看到的效果,右侧是有色盲的用户看到的效果。

当然完全色盲的用户群体也相当少见,患有这种缺陷的人眼里只有不同深浅的灰色。颜色感知的变化影响的整个视觉光谱,而不仅仅是一种颜色。

a11y-developing-21.png

你的初衷可能是选择一种大部分有色彩障碍的人都能识别到的颜色,但由于有各种色弱,且每种色弱的情况有轻有重,要选出这样一种颜色相当困难。不过橘色和蓝色还算能满足大部分情况。这就是为什么互联网产品里蓝色如此常见。

对于这些用户群体,唯一的原则是:别仅用颜色区分。比如上面的表单控件,可以在设计表单时,表单验证环节除了增加颜色之外区分之外,还可以添加一些区分对错的图标,甚至还可以添加一些提示信息。如下图所示:

a11y-developing-22.png

Facebook的注册表单在可访问性方面要比Twitter的注册表单更友好,特别是对于色盲的用户群体!

理论知识不够,工具来凑

要彻底的让自己的应用更具可访问性,需要的理论知识会很多,要对相关的规范有一定的了解,比如HTML5规范,WCAG规范,WAI-ARIA规范等,另外除了了解这些规范还是不够,还需要去实战,只有在实战过程中才能让自己在这方面更具经验。

另外,用户代理或辅助技术对这些规范的支持程度也不一样,同一特性在不同的用户代理和辅助技术上向用户呈现的效果也是有所差异的。

虽然掌握这些规范和相关知识并没有捷径,也没有速成法,但我们可以通过一些工具来帮助我们更好的构建可访问性的应用,也可以通过这些工具帮助我们快速了解构建Web可访问性相关的知识。

现在主流的现代浏览器都有很多这方面的优秀工具,比如Chrome浏览器:

image.png

就浏览器插件而言,我个人最喜欢的是 axe 和 Wave。使用浏览器插件来检测Web应用可访问性很简单,就拿axe为例吧:

image.png

浏览器除了插件之外还有自带的一些开发者工具,比如Chrome中的Lighthouse Audit就可以对可访问性做检测:

image.png

对于很多开发者而言,会使用可访问性CLI工具来审核自己代码的同学较少,毕竟有近63%的开发者不测试(也不检测)有关于可访问性相关的事项。部分开发者,特别是对于前端同学而言,出于习惯性,总是喜欢手动来检测。事实上,没有必要这么做,我们可以借助可访问性的CLI来帮助我们对Web应用进行自动检测。

在社区中,用来检测Web可访问性的CLI工具,最流行的应该是 pa11yaxe-cli。接下来,我们简单地来看看这两款CLI怎么实现可访问性相关的检测。

image.png

也可以在工程构建中使用ESLint插件:eslint-plugin-react 和 eslint-plugin-jsx-a11y,它们直接在你的JSX中识别和实施许多可访问性规则。将其与测试最终呈现的DOM工具(比如 react-axe )结合使用,可以帮助你找到并修复站点上有关于可访问性的问题。

image.png

如果你的文本编辑器开启了ESLint插件功能,在编辑器也会有相应的提示,比如我自己使用的VS Code,就会有相应的提示信息,当你把鼠标悬停在相应位置,会有更详细的信息:

image.png

虽然eslint-plugin-jsx-a11y可以帮助你轻松地检测到JSX中的任何可访问性问题,但它不测试最终输出的HTML代码。不过,我们可以借助react-axe这个库(它是通过Deque Labs的axe-core测试工具提供的一个包)来实现这一点。

image.png

注意,输出的错误信息有不同的级别提示:Minor(小错误)、Moderate(中等的)、Serious(严重的)和Critical(至关重要的)。如果输出的错误信息中看到了Serious和Critical标记时,表示对可访问性有严重的影响,需要开发者想办法来修复。

这些工具都有一个共同的特点,在每个错误提示的下面都有相应的指导链接,比如Chrome中的Lighthouse Audit 就提供了修复的链接地址,在对应的链接文章中有相关的指导原则。我们可以根据这些指导原则来修复无障碍的问题,同时也可以从中学习和积累无障碍优化方面的经验。另外维护Lighthouse Audit的团队在web.dev站点上提供了很多关于Web可访问性相关的知识,比如Accessible to all

image.png

还有 Accessibility audits 提供的相关链接,就是优化Web无障碍的一些指导原则:

image.png

如果你希望自己的Web应用被Chrome中的Lighthouse Audit 或其他检测工具拿到高分的话,还可以花一些时间深入的了解Lighthouse accessibility scoring 提供的相关信息:

image.png

另外,我也在小站上分享了一些有关于Web可访问性相关的文章,感兴趣的话可以点击下面的链接进行阅读:

技术有温,代码有爱,我们一直在为爱努力

前面我们花了很长的篇幅和大家聊了一些A11Y的理论知识和基础实践。掌握上面提到的技术点,我们可以让自己的Web应用具有一定的可访问性。但是在互动领域或者说互动项目中,掌握这些是不够的,因为互动的项目相比其他的项目来说:

  • 她更丰富
  • 她的交互更复杂
  • 她有游戏区域( <canvas> )
  • 她有动态更新
  • 等等

image.png

从左往向分别是 PK盖楼,618理想列车和淘金币小镇

再来看看今年的 超级星秀猫:

从这一年来对互动项目中碰到的无障碍缺陷统计来看,我们时常会碰到:

  • 焦点冗余
  • 焦点穿透
  • 互复杂交互组件
  • Canvas区域可访问性

接下来,我们通过一些具体的示例来看看是如何解决这些问题的。

会说话的互动,怎么把话说好?

屏幕阅读的功能是系统层面的功能,它的优势在于能够自动捕获内容焦点并且朗读出来,但是在互动等高复杂度页面中,我们往往会遇到几个典型问题:

  • 页面样式非常丰富,容易造成焦点多且杂
  • 信息表达方式依赖视觉,屏幕阅读出来的内容令人模棱两可

我们先来看下面这个场景,这是 超级星秀猫 互动主页中红包信息的组件。

image.png

这个组件想要传达的信息都是比较简单明了的,视力正常用户阅读不会存在理解不了的问题,但是如果没有针对使用屏幕阅读器的人士做出优化,因样式原因导致的焦点过多的问题就会带给他们这样哭笑不得的阅读体验,甚至是无法准确获得信息:

由此可以看到,焦点冗余带给无障碍化浏览的体验几乎是灾难性的,这就像是“让他们听一个三岁小孩给他们断断续续的背诵道德经”。为了解决这类问题,我们做出了这样的优化:

  • 多个焦点内容合并,整合碎片化的信息
  • 内容为听觉体验重新编排优化

效果如下:

在代码层面,我们做了这两件事:

  • 将各个细粒度过高的焦点元素设置为 aria-hidden="true"
  • 新建一个包含丰富信息的焦点元素,该元素在页面上不可见,但是能够被屏幕朗读功能聚焦

举个简单的例子,我们创建一个新的焦点元素,它对应赛事结果组件中这部分的信息:

image.png

<div className="sr-only">{`我方队名是${groupName}`}</div>

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    white-space: nowrap;
    clip: rect(0 0 0 0);
    clip-path: inset(100%);
}

同时我们把原先两个焦点元素设置为 aria-hidden="true" ,就完成了一次简单的焦点冗余优化,视障人士在浏览屏幕信息时就可以获得更顺畅并且更加能 听懂互动

而这只是让 互动把话说好 的第一步,冗余焦点与朗读内容的优化这件事情是可以往深度优化的,从冷冰冰的文字,到有温度的互动内容,既然我们已经跨出了这一步,就要把每一步都走好、踩实。

错综复杂的互动页面,怎样做到错中有序?

浮层与弹窗的层峦叠嶂

互动项目中往往存在大量的可互动元素,页面的层级也会因此变得比较复杂,举个例子,互动中最常见的弹窗与浮层元素。面对这些场景时,无障碍访问遵循的穿透原则就会带来一些不在我们期望中的问题:

  • 页面的层级信息会被抹平,点击可以访问弹窗下面的页面元素
  • 反复在各个层级页面中切换容易让用户无法正确获得信息

未命名.png

无障碍访问穿透示意

在弹窗与浮层元素的无障碍开发中,我们亟需解决的就是点击穿透的问题,而解决的方法有两种:

  • 给弹窗的所有元素添加 role 属性。
  • 在弹窗或者浮层出现期间,将页面上的其他元素设置为 aria-hidden="true"

在本次 超级星秀猫 互动主页的开发过程中,我们采用的是第二种方法,主要原因是本次活动的弹窗和浮层都是高层级页面元素,且出现时页面其他元素不可操作。我们会在弹窗出现和销毁两个阶段点,分别给页面其他元素添加和删除 aria-hidden="true" 的属性,示例代码如下:

// 弹窗出现
Array.from(document.querySelector('#module-container').children).forEach( // 遍历页面中所有组件、模块
  el => {
    if (el !== popup) { // 非弹窗组件全部设置 aria-hidden = true
      el.setAttribute('aria-hidden', 'true');
    }
  }
);

这样操作的优势在于,对于视障人士而言,当弹窗出现时,页面其他元素实际上也是不可访问的,保持了和健全人访问弹窗时页面表现的一致性。这类操作给我们的启发是:无障碍开发的原则是需要将页面的可访问性与正常浏览的情况保持一致,如果这个元素被盖住了,那么相对应的也要对其做好优化。在互动业务中,弹窗浮层的出现非常频繁,单页面的复杂度远超各种平铺页面,处理好弹窗浮层与页面之间的复杂关系,也成为了让互动页面说好话的重要一环。

Tab,各种Tab

相信你在玩各种互动游戏时都遇到过切换标签页的场景:手淘底部就有从“首页”到“我的淘宝”的五个标签页,而在这五个标签页中,又会有各自的子标签页。标签页带来的价值很简单:每个人的手机就那么大,想要在这么一点点空间中放下足够多的信息,标签页是性价比非常高的方案。

然而标签页的使用给无障碍开发提出了新的问题:本质上讲,标签页的切换意味着页面信息的变化,而视障人士如何知道他们现在处于哪个标签页呢?换句话说,我们需要建立标签切换的 Tab 和与之对应的页面信息之间的映射关系。

对应.png

Tab与内容的对应关系

一旦明确了建立这种映射关系的需求,实行起来就非常简单了,我们给每个 Tab  都加上三个属性:idaria-selectedaria-controls

  • id 为唯一标识,与 Tab 对应内容元素的 aria-labelledby 保持一致
  • 当前aria-selected 代表标签的选中状态
  • aria-controlsTab  对应内容元素 id 保持一致

这样一来,视障人士也能够轻易地判断出自己当前在哪个 Tab 下:

复杂交互组件

在Web应用中有些组件是带交互行为的,比如淘金币小镇中用户点击建筑物时有相应的提示信息:

这样的交互效果如果也要让屏幕阅读器这样的辅助技术具有相应的效果,比如操作屏幕阅读器的用户在某个建筑物上获得焦点时,双击之后能朗读出相应的提示信息。

要实现这样的效果,就需要使用ARIA规范中的一些特性。就拿上面这个示例来说,我们构建了一个 SvgToolTip 的组件:

image.png

我们来看该组件编译之后的DOM结构,以及相应的ARIA属性,角色,状态等使用:

image.png

其实该组件就是WAI-ARIA中的典型的 Alert** 控件。在Web中有很多类似的交互组件,WAI-ARIA Authoring Practices 1.1 提供了这些常见交互组件的可访问性应该怎么做

image.png

另外,Index of ARIA Design Pattern Examples 文档也提供了很多相关的最佳示例

image.png

如果你的业务中碰到和这些相似的组件,并且希望这些组件具有较好的可访问性,就可以参考他们来设计。

游戏区域可访问性的优化

互动项目和其他的Web应用(H5项目)还是有所差异的,其中最大的差异就是:互动的项目带有游戏化的场景,而且交互方式也更为复杂。其最的特色就是:游戏化场景和主交互元素相结合。如果用Web元素来描述的话就是:Canvas画布和DOM元素的结合。 ** 早期,为了让游戏区域能让辅助技术(比如读屏器识别),一直以来都是尽可能的将游戏区域中元素剥离出来用DOM来构建:

image.png

上图中绿色区域就是Canvas画布,也是游戏区域,在Web中有关于canvas中A11Y的处理至目前还没有较好的技术,因此接下来的内容会先忽略canvas中的内容。上图中高亮的都是DOM元素,而且这些高亮的部分也是链路交互元素。目前淘金币小镇就是这么来做的。

今年双11 超级星秀猫 的项目中,我们采用了另外的一种方式来为游戏区域构建可访问性。

image.png

该方案就是基于EVA JS的基础上扩展了一款服务于可访问性的插件 @ali/eva-plugin-a11y 。如果你是基于EVA JS开发的互动小游戏,就可以像下面这样来使用。

引入A11Y插件

import { A11ySystem, A11y, A11yActivate } from '@ali/eva-plugin-a11y';
import { Eva, addSystem } from '@ali/rax-eva';
addSystem(new A11ySystem({ activate: A11yActivate.ENABLE, debug: false }));

引入时注意 A11yActivate.ENABLE 时默认打开无障碍,打开无障碍时会用DOM的点击来触发点击,有可能造成点击次数和不开无障碍时的点击次数不一致,这次双11撸猫的次数在不开无障碍和开了无障碍后不同就是这个原因。

使用A11Y插件

在游戏区域中需要提供可访问性的游戏对象上添加相应的ARIA信息:

gameObject.addComponent(
  new A11y({
    interactive: true,
    hint: '我的猫,点击撸猫',
    role: 'button',
    tabindex: '-1'
  })
);

背后的思路

该思路是来自于AOM的:

image.png

我们DOM到一些辅助技术的工作过程大致如下:

image.png

基于该思路,在给游戏区域创建对象的时候也相应的创建DOM,这些和游戏区域相关联的DOM只有屏幕阅读器这样的辅助技术才能获取到。用一张简单地图来描述一下其工作过程:

image.png

A11Y是一个持续性的过程

虽然经过一年多来的探究和尝试,互动项目在Web可访问性方面取得了一点成绩,但其中还有很多东西我们需要继续努力。另外,A11Y不是一个短暂的过程,它应该是一个持续性的过程,我们应该持续探究这里面的技术点,通过技术给用户提供更好的体验。

最后,希望我们一起来A11Y努力,更希望你在下一个项目的开发伊始就将A11Y考虑进来。

你的努力会给他人带来幸福!