返回 登录
0

信息无障碍技术关隘

作者:温和,2010年进入腾讯,现任SNG社交用户体验设计部商业产品设计中心云平台前端开发组副组长、技术公益分会无障碍技术顾问。他还是W3C WCAG工作组成员。
本文为CSDN原创文章,未经允许不得转载,更多信息无障碍技术文章请关注信息无障碍知识库

无论是Web还是Mobile App,从它设计之初就是平等的,作者们不会刻意地去限制某一类或者某几类人群使用。但由于对Accessibility(信息无障碍,也翻译为:可访问性)的认知较少,加之在国内信息无障碍仍处于“公益”的范畴,所以其理念与技术体系不为人所知也是在情理之中,这也就导致老年人、低学历者和盲人等群体在使用软件的过程中产生很多障碍。比如,最近某大型生活类网站的验证码改为看图识物,表面上阻碍了机器人,但更多的是阻止了更多真实的用户。或许这个网站的作者并未想到自己拥有这样一部分用户。

残障的用户是多种多样的,老龄化、视觉、听觉、语言、文化、行动、认知、学习、神经学障碍都属于残障的范畴。由于软件大多依赖于视觉进行辨识,所以全球对于解决盲人使用软件有着比较丰富的解决方案,我将以盲人用户为例,细说信息无障碍技术的关隘。

盲人操作计算机系统和软件,除了是用我们的键盘(输入设备)以外,还需要两个重要的设备:screen reader(屏幕阅读软件)和声音外放设备(输出设备)。键盘(Mobile则是屏幕)用来切换焦点,屏幕阅读软件负责通过软件所在的宿主环境提供的API中的信息来转化成语音,最终通过声音外放设备告知用户当时的信息和操作。
在信息无障碍的知识体系里,屏幕阅读软件是典型的AT(Assistive Technology,辅助技术)。辅助技术包括软件和硬件,我们经常会在操作系统上看到的放大镜、大号鼠标、高对比度和assistive touch这些是软件,而布莱尔显示器则是硬件。它们底层的原理都是“翻译”宿主环境API中的信息,至于翻译的结果是机械化的还是人性化的,则是辅助技术自己来决定。比如:<h1>ISUX商业产品设计中心</h1>,这样一段代码,有的屏幕阅读软件会返回“ISUX商业产品设计中心”的声音,有的会返回“一级标题ISUX商业产品设计中心”,如果再人性化一些的屏幕阅读软件可能会翻译为“腾讯社交用户体验设计部商业产品设计中心一级标题”。这是辅助技术的体验多样性的一个典型例子。所以在确定用户使用的辅助技术份额后,你需要做的就是摸清楚这些辅助技术在解释API时的一些特点,从而编写相应信息,提供给用户更好的体验。推荐两个免费的Windows屏幕阅读软件,一个是国际化的NVDA,另外一个是国内的争渡读屏,使用他们去阅读相同的Web,你会发现明显不同,特别是在对一些语意化标签的处理上。苹果公司设备有专门的屏幕阅读软件VocieOver,通过“设置”→“通用”→“辅助功能”→“VoiceOver”即可开启;而Android平台下的是Talkback,国内手机厂商系统基本上都阉割了这个功能,在某些有良知的软件市场可以下载得到。

图片描述

图1 苹果的屏幕阅读软件VoiceOver

辅助技术访问一个Web,依赖于浏览器提供的API,通过这些API来获取网页的源代码(支持脚本动态内容和AJAX)。浏览器本身的API和支持能力也不相同,IE和Chrome就是两个不同的API,所以国内的屏幕阅读软件基本上是不支持Chorme的,因为会让开发成本增加。关于支持程度很好理解,就跟某些版本的浏览器不支持css的min-width属性或者不支持<ruby><rt></rt><rb></rb></ruby>等标签,虽然可以以某种样子来渲染却难以获取其实际的效果。这些API被称为Accessibility API。

图片描述

图2 Accessibility API

这些API包括HTML标签本身所标记的内容,如代码1所示。

<meta content="text/html; charset=utf-8" http-equiv="“Content-Type”/">
<title>腾讯云</title>

……
<li>腾讯云游戏解决方案</li>
……
<img src="“http://domain/img”" alt="“深圳的蓝天”">
……
<label for="“basketball”"><input type="“checkbox”" name="“interests”" id="“basketball”">篮球</label>
<label for="“football”"><input type="“checkbox”" name="“interests”" id="“football”">足球</label>
<label for="“running”"><input type="“checkbox”" name="“interests”" id="“running”">跑步</label>
<label for="“swim”"><input type="“checkbox”" name="“interests”" id="“swim”">游泳</label>
……

内容、标签、标签属性、标签个数,这四类API,浏览器对会有相应的API,辅助技术也可以很直接地去获取,但随着Web的交互越来越复杂、视觉设计越来越个性化以及越来越多地使用AJAX,只利用这四类API就难以完整反映出Web当前的内容和变化。

Amazon的一级商品分类列表有二十个列表项。而第五个列表项Kindle E-readers & Books包含着二级商品分类。在你编写这个模块的时候,你是多么的希望有一个<menu></menu>标签,然后用某一个属性来标记这个menu的名字,还可以利用某个属性标记Kindle E-readers & Books有一个弹出菜单。但就算是新发布的HTML5,也无法提供这么多语意的标签和属性。当然你可以使用一些针对辅助技术本身特性的方法来达到相同的效果,我之前也是这么做的。给标签加上title,编写几个存放说明文字的不可见元素,等等,不过这些方法都是不健壮的:无法跨平台,并且很难保证新版的辅助技术是否会改变“翻译”策略。是不是有点悲观?有一个好消息是,去年我所在的W3C工作组已经解决了这个问题(我是打酱油的)。

图片描述

图3 Amazon的一级商品列表

2014年3月20日,W3C的协议与格式工作组(Protocols and Formats Working Group,PFWG)发布了可访问富互联网应用(Accessible Rich Internet Applications,WAI-ARIA)1.0版及WAI-ARIA 1.0用户代理实现指南(WAI-ARIA 1.0 User Agent Implementation Guide)的W3C的正式推荐标准(W3C Recommendation)。中文版授权翻译工作也正在进行中。

WAI-ARIA约定了标准化的Accessibility API,它通过role属性来标记标签的角色,比如,<div role=“main”>……</div>表示这个标签中标记的是当前页面的主要内容;利用aria-前缀来标记角色的状态和属性,比如,<div class=“rich-btn” role=“button” aria-haspopup=“true” aria-pressed=“true”>辅助技术</div>,role=“button”表示这个标签所标记的内容是按钮,aria-haspopup=“true”表示这个按钮有弹出菜单,aria-pressed=“true”当前按钮是被按下的。
WAI-ARIA共定义了4类共73个role,分别是:Abstract Roles、Widget Roles、Document Structure Roles、Landmark Roles,其中Abstract Roles不能标记在标签上,详见http://www.w3.org/TR/wai-aria/roles;共4类35个states和properties,其中9个状态、26个属性,用来定义Widget Attributes、Live Region Attributes、Drag-and-Drop Attributes、Relationship Attributes,详见http://www.w3.org/TR/wai-aria/states_and_properties

图片描述

图4 Landmark 举例

通过WAI-ARIA,我们可以将Amazon的菜单编写成代码2,为辅助技术提供更多的API信息,帮助残障人士更好地获取信息并且方便地与Web进行交互。

<div id="“menu”" role="“menu”" aria-label="“shop" by="" department”=""> 
    <div role="“menuitem”" aria-selected="“true”" aria-haspopup="“true”">Kindle E-readers & Books       
        <div>sub-level menu</div>
    </div>
    <div>Fire Tablets
         <div>sub-level menu</div>
    </div>
    … 
</div>

一个好消息一般都会伴随着一个坏消息。WAI-ARIA中所定义的所有role、states和properties并未被浏览器和辅助技术完全支持。当前支持程度比较好的是Landmark roles(路标角色)。Landmark roles有8个值可以设置,application(应用)、banner(悬浮区)、complementary(补充内容区)、contentinfo(版权与隐私区)、form(表单)、main(主内容区)、navigation(导航区)、search(搜索区,如果表单只有搜索功能则定义role=“search”而不是role=“form”)。路标角色的目的就是帮助用户了解各个功能区所在位置并且进行切换,使用NDVA和争渡读屏可以按D键进行切换,按Shift+D键逆向切换,早年在iOS下使用Voiceover的时候改变VoiceOver Rotor(转子)到Landmark。

辅助技术都是通过源代码来认知软件本身,对于文本当然是迎刃而解,但像图片、视频、音频这样的多媒体信息,辅助技术是如何进行翻译的呢?这就引出了一个概念——等价替代方案。

什么是等价替代方案?假如你现在正在某个视频网站上看视频,但你发现你的声卡坏了,或者你没有耳麦等外放设备,你无法获得完整的甚至是全部的信息。那么这些靠声音才能传达给你的信息,比如,新闻播报、体育解说、电影台词这些就对你产生了障碍,想获得这些信息,我们可以通过字幕来解决,令到你可以获得最基本的信息,了解当前的视频、音频在讲什么,它们在传达什么信息给你。而字幕对于视频中的音频以及单纯的音频来说,就是等价替代方案。当然不可能完全等于。就像是美剧上的字幕,如果没有中文字幕你就很难了解故事的内容了。

单纯地提供字幕,可以解决听力损伤的用户访问时所面对的障碍,但对于盲人来讲困难仍在。因此,字幕的内容也要以编码的形式体现在代码之中,而不是把它和原始视频合并重新保存为另外一个视频,对于辅助技术来说,不可翻译的是这个媒体文件的本身,所以等价替代方案要考虑的不仅仅是一个群体的障碍,要尽量考虑更多的群体的障碍。图片一般推荐使用alt来存放替代信息。由于各个浏览器对视频相关的HTML5标签属性尚未完全支持,所以暂时使用js来驱动一个额外的字幕文本文件是一个比较不错的方式,不过不得不说,这个成本实在是很大。

假如,我们有一个交互需要双击事件才能驱动(当然这种交互方式应该是绝对避免的)。如果在视觉或者文本提示上不到位的话,那么一个新用户就难以在第一时间理解这个应该如何操作;一个老龄化用户由于行动障碍,如果这个点击区域较小,那么他们也无法通过鼠标精确地划到这个区域之上,在双击的时候可能也会导致鼠标移动;一个键盘用户,也许这个用户暂时没有鼠标或者盲人使用键盘,那么你期望他们用什么来双击?举这个例子是想告诉大家,不但内容上应有等价替代方案,在事件上也应该有相应的替代方案。最常见的是使用回车替代onclick、onfocus替代onmouseover和hover、onblur替代onmouseout。

合理地使用标签、属性和WAI-ARIA为整个Web的基础信息打下了一个坚实的基础。Desktop Software和Mobile App的开发也同样有着相同的原理,合理使用微软、app和google公司提供的标准代码来编写界面,遵守各公司的无障碍标准。这些几乎也是软件作者唯一可以做好的事情。毕竟,操作系统、浏览器和辅助技术对于Accessibility API的支持能力是软件作者控制不了的。如果软件的作者忽略这些基本的代码和等价替代方案,那一个盲人使用一个软件的时候,就跟你看图5的感觉是一样的(当然仅仅是举例,实际情况并非如此)。

图片描述

图5 忽略等价替代方案的示例

另外一件事情是软件作者的分内之事,但是大家往往没有考虑周全——提供符合逻辑的访问路径。其中,Mobile App最为严重。

普通用户使用软件,通过方位、视觉重点和信息来决定他的访问使用路径。辅助技术则是根据软件代码的顺序(包括动态生成和AJAX,也就是浏览器渲染之后的代码)来决定访问的顺序。因此,特别是盲人用户的访问路径是依赖于你的编码顺序,如果你仅仅是为了某种视觉效果而使用强大的CSS来布局,那么你的整个HTML代码顺序就有可能不符合一个常规的逻辑顺序。可能在界面左上角的某块的实际代码顺序是在文档相当靠后的位置。特别是Native App的代码顺序更要符合逻辑性,top bar和bottom bar以及中间窗体之间的顺序是否统一,让用户在使用同一款App时每个界面都有相同的功能区域顺序。内部的view是否符合产品操作和信息流的逻辑顺序。在这一点上,我们可能要探究的是信息的优先级问题,只有确定了信息的优先级,才能确保代码的编码顺序,但往往很多产品和团队忽略了这一点,很多交互设计师也把精力集中在了如何让交互更炫,而忽略了信息优先级的考究。更多的前端开发者们追求可用性上的酷炫,酷炫的动画,视觉的运动冲击,却忽略了最本质的代码的逻辑顺序,导致可访问性的障碍频频出现。

代码顺序也仅仅是一个好的开始,并不是结束,特别是Web。对于键盘用户(包括盲人用户)通过按Tab和Shift+Tab键切换焦点从而达到浏览网页,对于除可聚焦元素(锚点和表单元素)意外的所有元素,使用Tab键是无法聚焦的,比如最常用的div标签。通过对标签设置tabindex属性值等于可0~32767,以使这个元素获得焦点,利用键盘可以使其聚焦。tabindex值为0表示该元素可聚焦,其聚焦的顺序不会变化。如果一个元素的tabindex值为1,那么就表示,当页面载入之后,此元素应当被第一个聚焦,无论在本身在DOM的哪个位置。也就是说,就算他本身的DOM顺序比较靠后,但按Tab键,焦点首先会聚焦于此,在按Tab才按照可聚焦的DOM顺序进行切换。现实的问题是我们不可能给所有的都设置为可以聚焦,就仅仅为了键盘用户(盲人用户)。这里有一个区别,普通键盘用户是可以看到界面的、可以利用视觉浏览信息,键盘只不过是驱动其点击链接和交互的一种方式。而盲人用户却不同,不过这也无需担心,屏幕阅读软件中主要负责切换焦点的是光标键(上下左右按键),该机制调用宿主(浏览器)的接口,可以使焦点在所有的有内容标记的元素(非空标签)上进行切换。所以这里有一个设置tabindex的准则:如果你希望它可以被Tab键聚焦,那么请设置它。当然tabindex也可以让一个原本可以聚焦的元素变得不可以使用键盘聚焦(特指Tab键)。如果像<a href=http://isux.tencent.com tabindex=”-1”>腾讯社交用户体验设计部</a>这样,普通键盘用户利用Tab键就无法将焦点移动到这个链接上了。

了解了tabindex这一属性之后,你就可以使用js轻松控制各个元素获得焦点了。至于哪个元素获得焦点也是要考虑的重要问题:现在焦点在一个按钮上,你按了一下回车,这时候页面上弹出了一个alertdialog,但他的DOM大多数情况下都不会是紧紧地按着触发它的那个按钮,所以你不做任何处理的话,再按一下Tab,焦点是绝对不会到达这个对话框之上的,所以你要根据信息流的逻辑来设置焦点移动的顺序,要符合逻辑,符合信息流的设计。但这个对话框关闭时,焦点应该回到刚才触发它的那个按钮上,使得用户回归到原来的操作流程上。当你先从一个树形菜单的某个子菜单离开之后,应当给予这个菜单一个标记,当你再回到树形菜单控件时,焦点就应该在当初你离开的那个子菜单上。

2020年开始,各个软件将会发现信息无障碍是他们必须要关注的问题,到了2030年信息无障碍将会是每个软件作者必须考虑的问题,因为那个时候绝大多数读者已经面对着老龄化带来的困扰。

评论