欢迎访文我的博客YangChen’s Blog
前一阵子一直在开发一个无障碍项目,到现在算是告一段落了,利用这点时间打算整理下无障碍开发上的一些关键技术。这次开发任务还是蛮有挑战的,网上也没有找到什么系统性的学习资料,踩了不少坑,回炉也改了不少代码,所以对于这个项目的技术总结还是十分重要的。
要做无障碍开发,知道什么是无障碍这个概念是十分重要的。无障碍在词典中的字面意思是
在发展过程中没有阻碍,活动能够顺利进行
对于前端的无障碍开发,我的概念是:能够让色弱、色盲、盲人等一些视觉有障碍的朋友,顺利、流畅、准确、一致的获得网页上的信息,并能进行相应的页面的操作。
概念理解起来如果很抽象的话,可以下一个读屏软件例如NVDA、争渡等,然后随便打开一个页面,闭着眼睛体验一样,你就会发现十分令人抓狂,无法注册、无法订票、甚至最恶劣的情况是完全不知道这个页面提供了什么信息,就是给你读图片,编辑框等,然而你根本就不知道是什么图片,编辑框是写什么信息的。
这个问题很关键,先从几个问题开始入手。
所以,无障碍开发与正常开发有什么不同。概括总结下就是,正常发开中我们在乎的视觉信息的传递,页面上显示的bug这个显然是不能接受。而无障碍开发中,我们不但要兼顾上听觉的信息传递,使读屏器读出的信息与视觉信息一致,并且还要支持流畅的键盘操作,因为鼠标操作显示不适合盲人朋友的阅读。
听起来很奇怪,隐藏的内容为什么要访问呢?谁访问?这个就是让读屏器访问的,对于无障碍导航,或者需要让读屏器读出来做补充的,而且内容要隐藏的,就需要用到这个技术。
举个例子来说,打开bootstrap,然后按下tab键就能看到这个无障碍导航
这个无障碍导航在正常情况下是看不见的,只有获得焦点时才能访问。可能有人会有疑惑,用display:none
不就好了,当然不行啊,display:none
里的元素是不能被读屏器访问的。
隐藏访问的方式有很多,但是有些有很多坑,这里翻译下Hiding Content for Accessibility这篇文章的部分段落,来说明下各种隐藏方式的缺陷,以及常用的隐藏方式什么怎么由来的
.element-invisible { text-indent: -9999em; outline: 0; }
这个技术无法用在从右向左书写的语言中,如希伯来文和阿拉伯文
.element-invisible { height: 0; overflow: hidden; position: absolute; }
Apple’s Voice Over无法读出里面的内容,因为高度是0
.element-invisible { position: absolute; top: -999999em; left: auto; width: 1px; height: 1px; overflow:hidden; }
在这个技术中,如果焦点聚焦到了这个元素,屏幕将会滚动到这个元素的位置。PS.我个人开发中发现用这个方法,NVDA不会读出其中的内容
.element-invisible { position: absolute !important; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px, 1px, 1px, 1px); }
这是这篇文章的作者最终选用的方法,这个方法在IE和FF中很好,但是在Webkit(Chrome和Safari)和Opear下,会产生不必要的滚动条,取决于隐藏元素的布局和或在页面上的位置。
.element-invisible { position: absolute !important; height: 1px; width: 1px; overflow: hidden; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px, 1px, 1px, 1px); }
这也是我在本次项目中用的方法,很稳定,获得焦点时只要改变下相应属性的值即可,具体就不写了先。
表单元素也是需要隐藏访问,例如这个搜索框
这是通过图片放大镜这个图片来传递出这是搜索框的信息的,但是对于盲人朋友来说,他需要让读屏器读出来这是搜索,因此就用到下面要说的啦。下面的内容转自表单显式LABEL和隐式LABEL对屏幕阅读器用户的影响–更新
<label for="firstname">First name:</label>
<input type="text" name="firstname" id="firstname" tabindex="1" />
<input type="reset"/>
、<input type="submit"/>
, 图片按钮<input type="img"/>
以及脚本按钮<button></button>
不用使用显式label,因为它们已经有了隐式标签,如value和alt 属性值,button元素的内容。<label>First name: <input type="text" name="firstname" /></label>
<label for="firstname">First name:
<input type="text" name="firstname" id="firstname" tabindex="1" /></label>
使用屏幕阅读器NVDA和IE9测试发现,屏幕阅读器用户听到的提示内容是不同的:
这篇文章的作者最后得出的结论是:使用for 和 id 并且表单控件不放在label元素内是最健壮的方法。