HTML5-可访问性高级教程-三-

75 阅读1小时+

HTML5 可访问性高级教程(三)

原文:Pro HTML5 Accessibility

协议:CC BY-NC-SA 4.0

八、HTML5 和可访问表单

在本章中,你将学习在 HTML5 中创建可访问的表单。好消息是,以前使用 HTML 4 创建可访问表单时使用的许多技术在使用 HTML5 时仍然适用。您还将看到一些新元素,以及新的 HTML5 元素如何允许您在浏览器中进行更多的表单验证,而不需要复杂的脚本。

如果您不知道如何在 HTML4 中创建可访问的表单,不要担心——我将从头开始讲述这一切。

设计一个可访问的表单用户界面

您从上一章学到的关于创建可访问数据表的许多原则也适用于使用 HTML5 创建可访问表单。总的来说,“吻”这个咒语是适用的——不仅仅适用于可访问的形式!

表单确实受益于清晰、简单、简洁的布局。在任何时候,您都应该避免增加任何不必要的复杂性,并且在表单下,您需要在输入字段、复选框和其他元素及其相应的标签之间创建编程关联。这些实践是用 HTML5 创建可访问表单的核心。

当然,表单与数据表有很大的不同。表单是交互式的,而数据表不是。当涉及到使你的表单更易访问时,它们的交互特性确实增加了复杂性。特别是,表单的交互特性带来了如何进行表单验证的问题,以及当最终用户出错时应该怎么做。如何确保错误消息是可访问的?答案有两个部分:你必须首先让用户知道有错误,然后通知用户她需要做什么来纠正错误。稍后我会对此进行详细说明,但这些是可访问错误恢复的主要关注点。

一些形式良好的做法

你已经在第三章中看到了一些简单的表单,以及一些使用脚本的表单验证技术。出于礼貌,使用一些大量使用 JavaScript 的技术来进行表单验证并不有趣。它通常是复杂和尴尬的。使用早期版本的 HTML 创建更容易理解的错误消息的技术并不差。

首先,我将介绍 HTML5 中一些新的输入类型和元素。您将看到这些新元素是如何被设计得更容易创作的,以及它们如何减少使用脚本进行复杂验证的需要。您还将看到可访问的错误消息,并学习一些实践,引导您创建更容易访问和使用的表单——同样,表单也更容易创作和使用。所以这是一个双赢的方法。

Image 注意你在 HTML5 中遇到的很多东西都是从 Web 超文本应用技术工作组(WHATWG)的 Web Forms 2.0 规范移植过来的。这个想法是 Web Forms 2.0 是 HTML 4 中表单特性的扩展。Web Forms 2.0 提供了新的输入字段、用于定义约束的属性、用于声明性重复表单部分的重复模型、新的 DOM 接口以及用于验证和依赖项跟踪的 DOM 事件。Web Forms 2.0 也是记录现有实践的一种尝试。如果你喜欢一些书呆子火车定位,把你的浏览器指向[www.whatwg.org/specs/web-forms/current-work](http://www.whatwg.org/specs/web-forms/current-work)

【HTML 4 和 HTML5 之间表单元素的差异

在 HTML5 中,有 13 个新元素和许多新属性。然而,HTML 4 中也有许多您可能很熟悉的现有元素,它们仍然有效。所以值得再看一遍。

在 HTML 4 中,有许多元素可以用来创建各种输入框、组合框等等。这些与 FORM 元素一起使用来指定:

  • 表单的布局(由表单中使用的控件、它们的顺序和位置定义)。
  • 处理已完成并提交的表单的页面或脚本(采用action属性的形式)。
  • 将用户数据发送到服务器的方法(method属性,如post)。

在 HTML 4 中,FORM动作将采用以下通用形式:

`<FORM action="yoursite.com/contact" method="post"> ...form details...

`

这个基本语法在 HTML5 中保持不变。在表单本身中,可以(事实上,仍然可以)定义各种控件,以允许用户与表单进行交互,指定交互的性质,并阐明每个控件可能施加的相关要求。我们将在接下来的章节中回顾这些控件及其使用标准。

输入元素

INPUT 元素用于用户输入数据,如文本字符串(姓名、地址等)或数字。在 HTML 4 中,INPUT 元素有各种属性,这些属性决定了表单控件的输入类型。有几种 HTML 4 输入元素类型,如下所示:

  • 文本
  • 密码
  • 检验盒
  • 收音机
  • 使服从
  • 重置
  • 文件
  • 隐藏的
  • 图像
  • 按钮

所有这些输入元素类型都会在浏览器中创建一个控件,并且浏览器会继承这些类型的某些行为。如果输入类型是“密码”,浏览器会显示一系列星号(****),而不是真正的文本。稍后我们将研究新的 HTML5 输入类型。

输入类型的语法采用以下形式:

<input type = "text"> <input type = "password"> <input type = "checkbox">

HTML5 中新类型的语法遵循相同的结构。

SELECT、OPTGROUP 和 OPTION 元素

在 HTML 4 中,您可以找到 SELECT、OPTGROUP 和 OPTION 元素。

SELECT 元素在浏览器中创建一个菜单。菜单中的每个选项都由一个选项元素表示。如果需要将任何选项元素组合在一起,作者可以使用 OPTGROUP 元素对选项进行逻辑分组。如果用户有一个很长的选项列表,而你想把它们分成相关的部分,这是很有用的。

这采用了清单 8-1 中所示的形式。

***清单 8-1。*选择、选择组和选项元素

`        Fender     Gibson Rickenbacker       Gretsch     Martin     Lowden    `

字段集和图例元素

HTML 4 中的<fieldset><legend>元素背后的想法是它们给你的表单更多的结构。< fieldset>元素用于按主题对表单控件进行分组,<legend>就像是<legend>元素的父元素<fieldset>的内容标题。有点拗口!如果你还记得,我们已经在第三章的中看到了这些元素的使用。

Image 注意前面所有的元素在 HTML5 中仍然有效。

元素

<label>对于创建可访问的表单控件非常重要。元素的作用是为一个控件创建一个特定的标签。这个标签允许你在<label>名称和控件本身之间创建一个编程关联。这允许辅助技术(AT)如屏幕阅读器理解INPUT元素的用途。为输入控件选择一个合适的标签是很重要的,因为一旦INPUT字段获得焦点,如果标签正确的话,屏幕阅读器就会显示出<label>的名字。

for/id 方法

HTML 4 中易于访问、标签良好的表单控件使用一种叫做for/id的方法。在这里,您用来标识输入元素的标签采用了<label for="somename">的形式,并且通过给INPUT的 id<input id="somename">赋予相同的值,它以编程方式与INPUT控件相关联。清单 8-2 详细介绍了这种方法。

***清单 8-2。*使用 for/id 组合使输入文本框可访问

`

Create new account

   E-mail address:

Password:

`

name属性也被设计用来指定INPUT元素的名称,并用于标识控件组。它也用于表单提交。它不是由 AT 宣布的。

因此,包含在<label>[…]</label>之间的文本会在相应的输入字段通过键盘获得焦点后立即由 at 宣布。当您希望确保屏幕阅读器用户能够访问您的表单中的一些信息时,您可以将它包含在表单的<label>中。

表单控件的 HTML5 标签

HTML5 规范概述了另一种不使用前面的for/id方法来标记表单控件的方法。这种方式实际上并不新鲜,它实际上是将表单控件包装在一个<label>.中,它采用以下一般形式:

<label>Text to label control<input type="text"></label>

Image 注意如前所述,这个方法并不新,在 HTML 4 中就有了。在 HTML 4 中,通过使用各种标签的for属性指向控件,您还可以从技术上为一个表单控件分配几个标签元素。-但是,在 HTML5 中不能再这样做了。此外,AT 对这种方法的支持很差。

在 HTML5 中,规范建议您使用for/id方法或者在控件中包装标签。在下面的代码行中,我结合了这两种方法并将控件包装在一个标签中,同时还使用了for/id方法。这采用如下所示的形式:

<label for="a11y_label"> Text to label control <input type="text" id="a11y_label"> <label>

当我在 Mac 10.7 (Lion)上使用 VoiceOver 在 Safari 5.1 中测试它时,这很好。我还尝试在输入框之外运行更多的文本,这也是屏幕阅读器宣布的。例如:

<label for="a11y_label"> Text to label control <input type="text" id="a11y_label"> some extra useful info!</label>

有趣的是,我的朋友、Paciello Group (TPG)的辅助功能专家 Steve Faulkner 进行了一些广泛的测试,发现这两种方法在带 VoiceOver 的 Safari 5 上都不太好,但我发现现在可以了(或似乎可以了)。因此,这可能是对这些结构的支持有所改善的迹象。

Image 注意 Jared Smith 在 WebAIM 上发表了一篇非常有趣的文章,题为“语义自动化”VoiceOver 使用语义自动化来修复某些损坏的 web 内容。这可能意味着我发现的测试结果是高级启发式评估的产物,而不是 HTML5 标记的应用。我在这里提到的不是 for/id 方法(这是经过反复试验和测试的防弹方法),而是 HTML5 规范中推荐的在标签中包装控件的方法。欲了解更多详细信息,请访问位于[webaim.org/blog/semantic-automation](http://webaim.org/blog/semantic-automation)的 WebAIM 博客。

尽管 HTML5 规范建议的这种通过将控件包装在标签中来识别控件的新方法(原文如此)不使用for/id方法的显式关联,但如上所述,我发现它在 VoiceOver 中工作正常(但请参见前面的警告)。然而,就使您的表单更加防弹和使用旧的遗留 AT 而言,我建议现在坚持使用for/id方法。不要认为这是一种限制。如你所见,标记很简单,并且for/id方法得到了很好的支持。您可以放心地使用它,因为您知道屏幕阅读器用户也可以轻松地使用您的表单。

此外,HTML5 具有与 HTML4 相同的单选按钮、复选框等。

新的 HTML5 元素

下面是新的 HTML5 表单元素和属性的列表。

元素和列表属性

HTML5 扩展了 SELECT 和 OPTION 元素的功能,使您能够向用户提供建议的预定义选项。这可以通过使用新的<datalist>元素和list属性来实现。

您使用@list值指向< datalist>元素中的相同 ID。在清单 8-3 中,我添加了一个title属性,给屏幕阅读器用户一个如何使用控件的提示。

***清单 8-3。*使用

`     

     `

元素

这个新元素表示计算的结果。它与for属性一起使用。例如,您可以添加来自各种form元素的值。清单 8-4 受到了W3Schools.com网站上的一个例子的启发。

***清单 8-4。*利用<输出>

`

Enter Value 1: Enter Value 2: =

`

Image 注意[html5doctor.com/the-output-element](http://html5doctor.com/the-output-element)有一些使用<output>元素的有趣例子。

<进度>和<计>要素

浏览器中的<progress><meter>元素显示方式相似。图 8-1 显示了 Firefox 9 的一个屏幕截图。图 8-2 显示了 Opera 11.6 中同样的进度条。

Image

图 8-1 。火狐 9 中的<进度>元素

Image

图 8-2 。Opera 11.6 中的<进度>元素

Image 注意前面两个例子都没有以开箱即用的方式显示<progress>数据,我还没有看到可访问的实现。我所看到的最接近的东西是汉斯·希伦(TPG)和克里斯·布劳希(美国在线)的出色工作的一部分,他们作为 Aegis 项目的一部分,正在开发 JQuery 支持的、可访问的、支持 WAI-ARIA 的小部件和控件。有关更多信息,请将浏览器指向[access.aol.com/aegis/#goto_progressbar](http://access.aol.com/aegis/#goto_progressbar)

新的 HTML5 输入类型

HTML5 真正酷的地方之一是新的表单控件——尤其是各种输入类型。这对作者来说非常有用,因为它们消除了一些验证的复杂性(这并不有趣)。正如你将看到的,这些控件有特定的行为和交互模型。在 HTML 的早期版本中,我们习惯了相当简单的输入类型,例如文本、密码或搜索。

Image 注意你可以用或者不用左双引号(")或者右双引号(")来写下面的类型。所以<input type="tel"><input type=tel>都有效。我在这里把它们写成<input type="tel">,因为这是我的偏好。当用户代理遇到它不理解的类型时,它会默认将控件显示为通用的text类型输入。

在 HTML5 中,类型状态决定了控件是哪种输入。所有的新类型几乎都像他们在电视上说的那样。下面几节将介绍完整的类型列表。

隐藏(类型=隐藏)

这采取以下形式:

<input type="hidden">

hidden类型表示终端用户看不到的一些值。

电话(类型=电话)

这采取以下形式:

<input type="tel">

尽管这种类型显然是用来输入电话号码的,但并不需要特定的电话模式。这是因为世界上有各种有效类型的电话号码。

URL (type="url ")

这采取以下形式:

<input type="url">

该控件用于输入 URL。这种输入类型和下一种输入类型(电子邮件)都需要(并强制执行)预期的语法。这对于客户端验证非常有用。

电子邮件(type="email ")

这采取以下形式:

<input type="email">

该控件用于输入电子邮件地址。如前所述,这种输入类型和前一种类型(对于 URL)都需要(并实现)预期的语法。

密码(type="password ")

这采取以下形式:

<input type="password">

这是用来输入密码的。其形式如图图 8-3 所示,您应该很熟悉。

Image

图 8-3 。密码输入类型

你可能不熟悉的是当屏幕阅读器将焦点放在密码控件上时的行为。考虑以下用于生成控件的代码:

`

Password:

`

控件的<label>通知屏幕阅读器用户控件的用途。然后,当它接收到焦点并且屏幕阅读器用户开始输入一些字符时,输出是(取决于屏幕阅读器)一系列点击噪声,在每个按键之后发出声音。如果控件中出现一系列星号,则输出为“星号、星号、星号”等。换句话说,不公布正在输出的实际字符,从而维护了盲人用户的隐私。

日期和时间控件

以下是向 HTML5 表单添加日期和时间控件的新输入类型。它们采取以下形式:

<input type="datetime"> <input type="date"> <input type="month"> <input type="week"> <input type="time"> <input type="datetime-local">

让我们把它们放在一起形成一个简单的形式,如清单 8-5 中的所示,并看看不同的浏览器如何呈现它们。

***清单 8-5。*使用日期和时间控件

`

Datetime:

Date:

Month:

Week:

Time:

Time:

`

清单 8-6 显示了一些简单的级联样式表(CSS ),用于将它们组合在一起。

***清单 8-6。*日期/时间表单的 CSS

`label          { width: 3em; display: block; margin:5px; }

input    { width: 5.5em; float: left; display: block; margin-top:-25px; margin-left:90px; padding:5px; }`

最后,图 8-4 、图 8-5 和图 8-6 分别是 Safari 5.1、Firefox 9 和 Opera 11.6 中的表单截图。

Image

图 8-4 。Safari 中新的日期和时间控制

Image

图 8-5 。火狐浏览器中新的日期和时间控件

Image

图 8-6 。Opera 中新的日期和时间控件

请注意三种浏览器呈现控件的方式之间的差异。Safari 会在每个输入控制的右侧显示一个微调控制。Firefox 没有,Opera 为<datetime>输入以及timedatetime-local控件都提供了微调控件。

Image 注意微调控制用于通过选择适当的箭头来上下调整数值。在撰写本文时,它们无法通过 Safari 5.1 (Mac)中的键盘进行本机访问或聚焦。它们不会在 IE9 或 Firefox 8 (PC)中显示。尽管日历日期选择器确实可以在 Opera 中显示,但 Opera 并不是一个非常屏幕友好的浏览器。当你读到这篇文章的时候,Internet Explorer 10 已经发布了,它承诺提供更好的 HTML5 支持。它在实践中会这样做吗?时间会证明一切。

数字(type=""number " ")

数字输入控件采用以下形式:

<input type="number">

这是一种新型的表示数字的控件。如果您使用以下代码构建它,并在一些不同的浏览器中查看它,您将看到浏览器默认呈现 HTML5 的方式的可变性:

`

Enter a Number:

`

图 8-7 、 8-8 和 8-9 展示了各种浏览器如何渲染这段代码。

Image

图 8-7 。Safari 中的“数字”输入类型

Image

图 8-8 。Opera 中的“数字”输入类型

Image

图 8-9 。Firefox 中的“数字”输入类型

范围(type="range ")

输入类型是一个有趣的新控件。它允许用户使用滑块控件在表单中输入值。该代码采用以下形式:

`

Use slider to enter a value:

`

range输入控件在支持它的浏览器中可视化显示,如图图 8-10 和图 8-11 所示。

Image

图 8-10 。Safari 中的范围输入

Image

***图 8-11。*歌剧中输入的音域

在撰写本文时,IE9 (PC)或 Firefox 9 (MAC/PC)都不支持 Range。不过,Chrome 确实支持它。有趣的是,在测试中,Chrome 浏览器不仅可以通过原生键盘访问控件,还可以反馈滑块的当前值。据我所知,目前没有其他浏览器能做到这一点。为了使滑块控件更容易访问,您可能需要提供一个脚本化的解决方案,以便 AT 能够宣布滑块的当前值,这样屏幕阅读器用户就可以知道他们在哪里。

Image 注意要获得一些可访问且不引人注目的 JavaScript 支持的 HTML5 范围型控件的好例子,请将浏览器指向[www.frequency-decoder.com/demo/fd-slider](http://www.frequency-decoder.com/demo/fd-slider)。你可以看到这些聚合填充通常不使用原生的范围,而是使用 CSS 来样式化控件,WAI-ARIA 来添加语义,JavaScript 来捕捉交互。

numberrange输入类型都可以接受以下新的 HTML5 属性:minmax。这些属性允许您设置数值控件或范围控件可以接受的最小值和最大值。

它们采取以下形式:

<input type="range" min="1" max="5">

还有一个新的step属性,它允许您以细粒度的方式设置输入值向上或向下跳跃的数量。如果您希望用户输入向上或向下跳跃值 5,可以使用如下代码:

<input type="number" step="5">

颜色(type="color ")

这种控制采取以下形式:

<input type=”color”>

这是一个颜色选择器类型输入。在我看来,这是一个奇怪的表单控件,因为我很难想到它的用途。在撰写本文时,只有 Opera 在浏览器中呈现了有趣的控件(如图 8-12 所示)。

Image

图 8-12 。歌剧中的色彩输入

HTML 4 中的其他控件对您来说应该很熟悉,比如复选框、单选按钮、文件上传控件、提交按钮、重置按钮和搜索输入。

新的 HTML5 表单属性

以下部分列出了来自“HTML5 与 HTML4 的区别”文档的 HTML5 新增的属性。您可以在[www.w3.org/TR/html5-diff](http://www.w3.org/TR/html5-diff)找到该文档。

自动对焦属性

可以在input控件(除了当type属性为hidden时)和selecttextareabutton元素上指定新的autofocus属性(@autofocus)。它提供了一种在页面加载期间聚焦表单控件的声明性方法。

使用@autofocus属性通常采用以下形式:

<input type="text" name="firstname" autofocus>

创作和添加到您的项目中非常容易。@autofocus属性是 HTML5 中一个有趣的新属性,它有可能在创建可访问的错误恢复中很有用。这可以通过在表单被验证后使用它自动聚焦到第一个有错误消息的字段来实现。如果使用这种方法,重要的是要确保错误消息的任何内联描述也作为控件标签的一部分,或者如果页面的另一部分存在错误,使用aria-described by来指出错误。

仅仅使用autofocus属性将焦点放在一个字段上是不够的,即使它是发生错误的正确字段,并且没有清楚地解释错误是什么以及如何修复它。

新输入元素属性

INPUT 元素有几个新属性来指定约束:autocomplete, min, max, multiple, patternstep。其中一些属性在关于range输入类型的章节中讨论过。还有一个新的list属性可以和datalist元素一起使用。

目录名属性

inputtextarea元素有一个名为dirname的新属性,它使得用户设置的控件的方向性也被提交。

新的 TEXTAREA 元素属性

元素还有两个新属性:maxlengthwrap。这些属性控制最大输入长度和提交的换行行为。

novalidate 属性

表单元素有一个novalidate属性,在任何情况下,当您不想执行任何验证而只想提交表单时,都会用到这个属性。

新的输入和按钮元素属性

inputbutton元素有formactionformenctypeformmethodformnovalidateformtarget作为新属性。如果存在,它们将覆盖表单元素上的actionenctypemethodnovalidatetarget属性。

占位符属性

可以在inputtextarea元素上指定一个新的placeholder属性。它表示旨在帮助用户输入数据的提示,如下所示:

<input type=email placeholder="mr.pussels@bigcat.com">

新的@placeholder规范了表单域中占位符文本的使用。对此我百感交集。传统上,占位符文本执行几项任务。首先,通过显示输入控件所需内容的样本,帮助视力正常的人理解输入控件的用途。它还被用来描述控件的目的(在 Web 的早期它并不支持),支持input类型的title属性,或者其他标记机制。

然而,这种情况已经有一段时间没有出现了,像这样添加占位符文本会产生一些问题——例如,如果禁用了脚本,输入控件的内容就不会被清除。在焦点上清除输入字段的内容当然是一种有用的技术,但是在较老的用户代理中,它回避了 JavaScript 关闭时会发生什么的问题。我告诉你会发生什么。用户输入的文本与占位符内容混合在一起。例如,如果在 HTML 的早期版本中,你有一个类似于刚才显示的电子邮件的输入类型,并且你输入了字符串“josh@animalsanctuary.com”,如果你没有使用脚本来清除该字段或者如果它是关闭的,你将得到一个类似于图 8-13 中的例子的字符串。

Image

图 8-13 。与用户输入文本混合的占位符文本

好消息是,当大多数老用户代理,如浏览器,遇到placeholder属性或任何他们不理解的新 HTML5 输入类型时,大多数只会默认显示一个输入框。例如,考虑清单 8-7 中的代码以及由此产生的屏幕截图(图 8-14 )。

***清单 8-7。*一个 HTML5 输入类型

`

HTML5 forms:Placeholder

HTML5 Form placeholder

Address: `

浏览器中的渲染结果如图 8-14 所示。

Image

图 8-14 。旧浏览器呈现为文本字段的 HTML5】

Image 注意在支持@placeholder的新 HTML5 浏览器中,焦点上的内容被清除,根本不需要任何脚本。这使得创作更加容易。此外,旧用户代理的默认行为意味着您可以使用它,而不必太担心旧用户代理会出现问题。

但是,需要注意的一个问题是占位符文本的颜色对比度很差。这对低视力的计算机用户来说是个问题。例如,考虑 Safari 5.1 ( 图 8-15 )和 Opera 11.5 ( 图 8-16 )的屏幕截图。

Image

图 8-15 。Safari 中占位符文本的颜色对比

Image

图 8-16 。Opera 中占位符文本的颜色对比

你注意到色彩对比有多差了吗?色彩对比度差会使有视觉障碍的人很难看到屏幕上的内容。请记住,许多有视力障碍的人根本不使用。它们通过使用浏览器控件来调整文本大小,或者通过使用系统范围的高可见性选项等等来实现。所以在你的网页内容中有好的、强烈的颜色对比是很有帮助的。

在 HTML5 中,您可以对各种输入类型进行样式化,但是您必须针对特定的浏览器,并且提到您想要样式化的属性。

要设置输入框的样式以使占位符文本变暗,可以使用 CSS3 选择器,其形式如下:

`::-webkit-input-placeholder {    color: #333333; }

:-moz-placeholder {    color: #333333; }`

Image 注意Safari 和 Chrome 等 webkit 浏览器有特定于供应商的前缀,基于 Mozilla 或 Gecko 的浏览器也有前缀。在撰写本文时,许多浏览器制造商开始不再需要在一些 CSS3 声明中使用前缀。因此,不用编写特定于供应商的声明,很快您就可以声明类似“border-radius”的东西,浏览器就会正确地处理它。IE9 在这方面给人留下了深刻的印象,但是对于一些选择器来说需要“ms”前缀。

新的表单属性

用于input, output, select, textarea, button, label, object,fieldset元素的新的form属性允许控件与表单相关联。这个想法是,元素可以放在页面上的任何地方,而不仅仅是作为form元素的后代,并且仍然与表单相关联。该规范给出了以下示例:

`Email:  <input type=email form=foo name=email>

`

然而,这个例子并没有真正说明这种新模式的潜力。现在表单控件可以从它的父控件中分离出来,放在<表单>[…]</表单>标记之外,如果作者需要这样做的话。

清单 8-8 中的例子应该让这一点更清楚。

***清单 8-8。*使用新的表单属性

`

First Name:

Last Name: Your Email:

`

清单 8-9 提供了一点 CSS 来呈现表单,并给它一些基本的定位和样式。

***清单 8-9。*表单 CSS

`

#form_container { display:block; width:100%; max-width:190px; font-family: Lucida Sans Unicode, Lucida Grande', sans-serif; color: #C90; background-color:#333; margin:10px; padding:10px; border-radius: 19px; }

#content_2           { display:block; max-width:190px; font-family: Lucida Sans Unicode, Lucida Grande', sans-serif; color: #C90; background-color:#333; margin:10px; padding:10px; border-radius: 15px; }

label          { width: 3em; display: block; margin:5px; }

input           { width: 9.5em; float: right; display: block; margin-top:-40px;}

#extra_info { width:90%; max-width:inherit; display: block; font-family: Lucida Sans Unicode, Lucida Grande', sans-serif; color: #C90; background-color:#333; border-radius: 15px; }

#submit          { margin:10px; }

::-webkit-input-placeholder { color: #ffffff; }

:-moz-placeholder { color: #ffffff; } `

图 8-17 是从 Safari 浏览器获取的表单的屏幕截图。

Image

图 8-17 。工作中的表单属性

这种模式可能会变得更加流行,当然,引用传统<form>结构之外的元素的能力有可能创造出新的交互形式(原谅我的双关语)。在这种情况下,因为我可以向文本区域添加一个title属性,所以屏幕阅读器将能够向用户提供补充信息。在没有标签的情况下,当控件获得焦点时,输出表单控件上的title属性的内容。给表单控件一个标题而不是标签,是向最终用户提供可访问信息的一种可接受的方式,前提是控件的目的从其视觉呈现上也是显而易见的。在这种情况下,文本“还有什么要说的吗?”充当视觉提示。您可能会发现,在构建表单时,您可能不想标记其他控件。

如上所述,这个新的form属性可以添加到input, output, select, textarea, button, label, object,fieldset元素中。一如既往,问题是在浏览器和 AT 中对它们的支持。随着这种新模式的普及,支持度无疑会提高。

Image 注意在表单控件上使用title属性或(@title不同于在图像上使用@title属性。虽然你不能确定屏幕阅读器是否会在图像或图形上获取@title的内容,但是当用于表单控件时,它要健壮得多。所以你可以放心使用。

新的必需属性

新的required属性(或@required)适用于input, select,textarea控件,并在表单验证和错误恢复中发挥重要作用。它表示用户必须填写一个值才能提交表单。对于一个select控件,第一个option元素必须是一个带有空值的占位符,如下面的代码片段所示:

<label>Color: <select name=color **required**>  <option **value=""**>Choose one  <option>Red  <option>Green  <option>Blue </select> </label>

新的屏幕阅读器对 HTML5 @required的支持非常好。旧的屏幕阅读器根本不会识别该属性。一种解决方法是结合使用 WAI-ARIA 属性aria-required="true"和 HTML5 @required。这个想法是,支持 WAI-ARIA 但不支持 HTML5 的旧屏幕阅读器将获取aria-required="true"属性,最终结果将是,它们将被通知它们已经聚焦于所需的控件。这方面的代码(基于规范中的上述示例)如下:

<label>Color: <select name=color **required aria-required="true"**>  <option **value=""**>Choose one  <option>Red  <option>Green  <option>Blue </select> </label>

这个例子有一些缺点。首先,一个既理解 HTML5 代码required又理解 WAI-ARIA 代码aria-required=”true”的屏幕阅读器将输出“Required”两次。这可能是一种痛苦,尤其是当有许多必填字段时。你可以争辩说这是一个防弹的方法,但是用户体验可能还有很多需要改进的地方。此外,使用这种方法,不理解 HTML5 代码或 WAI-ARIA 代码的屏幕阅读器怎么办?在这种情况下,他们将无法为最终用户做任何有用的事情。

不幸的是,作为一个作者,你没有办法发现一个人在使用什么样的 at。向后兼容旧技术的一个更可靠的方法是在控件的标签中包含单词“Required”。这采取以下形式:

<label> Choose a color [Required] </label>

它相当简单,对老用户代理和新用户代理都适用。这也是一种使表单可访问的更古老的方法,仍然有一些吸引力——有一些!但是,您可能不希望在控件的标签中出现“[Required]”,但这是您的决定。其优点是,它对视力正常的用户和使用新旧屏幕阅读器的用户都有效。

这一期特别适合强调一些 WAI-ARIA 代码格式和 HTML5 之间的相似之处。在这种情况下,这两者之间肯定存在一定程度的冗余。在这种情况下,aria-required="true"的优势(在很多 ARIA 1.0 的情况下也会如此)是在过去几年中,屏幕阅读器已经实现了支持,在撰写本文时,它略微领先于 HTML5。然而,我很确定,当 HTML5 支持增加时(就像现在一样),这一切都会改变。最终,您决定如何创作应该基于测试和什么最适合您的需求。最后,尽管你可能不得不在某处妥协,但还是要采用任何可行的方法。

Image 注意type属性被隐藏或者当一个图像或某种按钮类型如提交按钮被使用时,@required将不被使用。

禁用的属性

fieldset元素现在允许disabled属性和name属性,前者在指定时禁用所有子控件,后者可用于脚本访问。

HTML5 表单验证

表单验证是从用户那里获得良好数据的底层机制的重要组成部分,也是确保当出现错误时,您可以准确地通知用户哪里出错了。所以验证也是错误恢复的第一阶段。

首先(如前所述),您可以使用required属性和/或aria-required="true"(或者两者的组合)。

如果提交的表单没有填写必填字段,Opera 有一个有趣的required属性实现,如图 8-18 中的所示。

Image

图 8-18 。Opera 11.6 必填字段

Firefox 在这种情况下也有一个有趣的实现:默认情况下,它也用红色突出显示必填字段。你可以在图 8-19 中看到效果。

Image

图 8-19 。火狐 9 必填字段

在“在浏览器中”验证方面,Firefox 也有一个非常好的功能:“请填写这个字段”的消息是由屏幕阅读器宣布的——至少在我用 JAWS 12 和 Firefox 9 (PC)进行的测试中是这样。这太棒了。不仅发生错误的字段接收焦点,而且当焦点被带到字段时,标签也被再次读出。这是完全可以接受的,也是执行验证和错误恢复的一种容易实现的方式。Chrome 也会显示一条类似于上面提到的其他浏览器的错误信息,但它不能像 Firefox 9 那样开箱即用。

遗憾的是,IE9 不支持这些特性。

HTML5 表单中模式的使用

在 HTML5 表单中,您还可以检查用户输入是否与预期匹配——这样您就不会在数值字段中得到文本字符串,或者得到正确的电子邮件地址。您可以使用新的pattern属性来帮助验证。这个属性告诉浏览器在用户输入后寻找一个模式,所以这个模式可以是一个数字字符范围或一个特定的文本字符串。例如,英国邮政编码可以采用以下形式:

Image

如果这看起来很复杂,不要担心。网上有很多资源,我是通过 Thinkvitamin.com 的网站找到这个的,叫做“html5pattern.com”,里面有很多。因此,如果您想在项目中包含这些类型的模式,请将您的浏览器指向那里。

可访问的错误恢复

在创建可被尽可能多的受众使用的表单时,可访问的错误恢复是一项非常重要的技术。因此,在 HTML5 中使用的任何新方法都必须具有一定程度的向后兼容性,这一点很重要,因为并不是每个人都在使用最新的浏览器,或者,正如我多次指出的,最新的。因此,虽然新的 HTML5 语言非常强大,但用户代理支持的问题是一个经常出现的限制,您必须提供。

您应该了解可访问错误恢复的几个阶段:

  1. 让用户知道有一个错误。
  2. 让用户访问错误,并提供如何修复错误的说明。
  3. 允许用户重新提交表单。

正如您在验证一节中看到的,一些浏览器确实支持新的 HTML5 属性,如required,并且可以为每个有错误的字段提供焦点(取决于代码中的源代码顺序)。当输入字段在支持的浏览器中用适当的<label>,正确标记时,对于屏幕阅读器用户来说,这通常是修复错误的足够信息。然而,在测试中,这仅适用于 Firefox 9 和 JAWS(从屏幕阅读器用户的角度来看)。然而,这是一个好迹象。如果支持这些 HTML5 方法来帮助验证,并在某种程度上帮助错误恢复,就有可能在不编写更复杂的错误恢复方法的情况下完成这两项工作。

然而,许多浏览器根本不支持这种方法。那么,如何以一种既适用于旧浏览器又适用于新浏览器的方式来支持可访问错误消息这一重要问题呢?

以下是一种可访问的错误恢复方法,适用于新旧浏览器。

Image 注意虽然我多年前在 WebAIM 网站上遇到过类似的方法,但这个实现来自 Peter Krantz 开发的“标准 Schmandards”网站。非常感谢彼得允许我在这里复制它。另外,Peter 还在数据可视化和系统互操作性方面做了很多其他有趣的工作。有关更多信息,请将浏览器指向[www.peterkrantz.com](http://www.peterkrantz.com)

这是一个简单的方法,相当可靠。考虑图 8-20 中所示的形式。

Image

图 8-20 。带有必填字段的登记表

清单 8-10 显示了表单的 HTML 格式。

***清单 8-10。*登记表代码

`

Please complete the following form to create your account.

Personal details
* Name:
* Age:
Country:
Sweden United States Japan
`

现在,如果提交了表格,并且两个字段都为空,则会显示图 8-21 中的错误信息。

Image

图 8-21 。必填字段的错误消息

产生该错误信息的代码如清单 8-11 中的所示。

***清单 8-11。*错误信息的代码

`

  

2 errors were found in your registration.

  

Please correct these errors and submit the form again:

  

`

一些 JavaScript 用于关注用户可以用来解决问题的相关字段:

function setfocus(objectid) { if(document.getElementById(objectid)) { document.getElementById(objectid).focus(); }  }

前面的代码可以通过键盘触发,所以完全可以访问。错误消息也非常清楚,并向用户概述了错误和可以采取的补救措施。相当整洁!

使用 JQuery 进行表单验证

还有一个很好的 JQuery 表单验证插件,可以用来验证表单并提供可访问的错误消息。将你的浏览器指向 NOMENSA 博客,寻找一个关于如何做的优秀教程:[www.nomensa.com/blog/2010/accessible-forms-using-the-jquery-validation-plug-in](http://www.nomensa.com/blog/2010/accessible-forms-using-the-jquery-validation-plug-in)

结论

在这一章中,我们看了一些旧的和新的 HTML 元素和属性,你可以用它们来构建可访问的表单。到目前为止,并不是所有的新元素都被支持,但是这将会改变。此外,您还看到了如何进行一些客户端验证,以及一些可访问的错误消息。在下一章,我们将着眼于可用性和以用户为中心的设计。

九、HTML5、可用性和以用户为中心的设计

虽然本书的大部分内容都集中在 HTML5 语言的技术方面,但是您还应该考虑其他方面,以确保您的项目可以被尽可能多的受众使用。本章涵盖了你会发现有用的领域,比如迭代开发方法、参与式设计、使用焦点小组和调查进行研究、专家评估以及人物角色的使用。

首先,如果可访问性主要是关于残疾人的,那么什么是可用性

什么是可用性?

可用性是人机交互(HCI)的一个子集,它着眼于用户体验的质量,并试图理解如何改进它。可用性作为一门学科,试图确定用户完成一项任务有多成功,以及设备或界面使用起来有多令人满意。这可以针对你能想到的任何不同群体来确定,例如视力受损或失明的人和老年人,但也可以针对无残疾的用户来确定。

Image UX,或者说用户体验的面积,这些天在扩大。这在很大程度上是由于消费者选择的力量,例如,如果潜在客户对你的服务不是百分之百满意,他们可以很容易地获得你的服务的替代品。

可用性有不同的定义,我们会看几个,因为它们有细微的差别,有各自的含义。可用性的一个流行定义如下:

“衡量用户完成一项任务的难易程度。在网页环境中,这关系到用户从给定的网站上找到所需信息的难易程度。1


1

这个定义关注的是用户能够完成特定的任务,这显然非常重要。然而,这是全貌吗?

另一个有趣的定义是这样的:

系统学习或使用的容易程度。易用性或易学性的品质因数或定性判断。一些评估可用性的方法也可能将可用性表达为一个量化指标。”2

我喜欢这个,我在这里提到它是因为它讲述了用户学习这个系统有多容易。对我来说,用户界面设计的一个很好的经验法则是:如果你必须提供如何使用它的说明,它已经太复杂了!

理想情况下,你的网站和应用的用户应该直观地得到它。当然,这在许多领域是不可能的。举例来说,用户不只是学会如何驾驶飞机。事实上,有一些灾难降临到飞行员和外科医生身上的故事,例如(或者更明确地说,乘客和病人)因为 UI 的复杂性。没有人想在飞机坠落时,为了弄清楚仪表盘上闪烁的模糊错误信息是什么意思,而不得不去寻找和解读一本手册。

Image 提示如果你真的想了解这类科技恐怖故事,以及讨论对更多“人类”技术的更广泛需求,可以看看本·施奈德曼的书莱昂纳多的笔记本电脑:人类需求和新的计算技术。这表明用户友好远非空洞的概念。

第三个定义是最有趣的一个,因为它超越了干巴巴地看着用户需要做的任务,提到了用户在使用 web 界面时的满意度。

特定用户在特定环境中实现特定目标的有效性、效率和满意度。与‘易用性’同义。”3

这个最终的定义通过关注用户体验的质量,而不仅仅是采取一种机械的、基于任务的方法,将可用性理念带到了一个更高的层次。这就是用户测试非常有用的地方,因为它是评估用户体验质量的一种极好的方式。


2

3

Image 稍后我会在用户测试上多说一些。用户测试是一个很好的工具,可以会见最终用户,并从他们那里获得对用户界面质量非常有用的反馈。没有什么比听到你的一个用户高兴地说“我发现使用那个网站真的很容易,我可以做我想做的事情”更能说明“成功”了。我会回来的。”此外,没有什么比用户沮丧地威胁要把显示器扔出窗外更能说明“失败”的了。用户测试是这种反馈的关键。

可用性之父之一的唐纳德·诺曼在他的网站上说了这样一句话,关于获得用户对系统可用性的反馈的最好方法:

“我警告说,逻辑分析不是预测人们行为的好方法(焦点小组或调查也不是):观察是关键[……]对于产品和服务来说,我是美丽、快乐和乐趣以及行为和功能有效性的拥护者。”4

可用性就是看一个界面的可用性、直观性、用户友好性和简单易用性。作为一门学科,它还研究用户交互的心理学,或者说认知人类工程学。它试图理解用户如何感知他们通过观看用户界面或设备或与用户界面或设备交互而接收到的指令。

Image 虽然易访问性和可用性是两个不同的领域,但是两者之间有着非常紧密的联系。以下技术经常在项目的准备阶段使用,如果足够小心地使用这些技术,这些需求收集和原型阶段可以帮助作者在项目的后期避免 UI 设计中非常严重的错误。

我也强烈推荐唐纳德·诺曼的书。特别是优秀的(既好玩又短小易读)日常用品的设计(封面上有其与众不同的茶壶)。他谈到了设计心理学,并为良好的交互设计制定了一些基本规则。例如,他提出的一些简单而深刻的观点被称为“评估的鸿沟”和“执行的鸿沟”我相信你在网上没有意识到这两个问题,意识到它们将帮助你设计更好的 HTML5 界面。

根据他的书,“当系统以一种容易获得、容易解释的形式提供关于其状态的信息,并且与人对系统的思考方式相匹配时,评估的鸿沟就小了。”这个鸿沟描述了这样的情况:一个网站没有以一种直观和容易理解的方式告诉你,或者它正在做什么或者它处于什么状态——或者它甚至没有给你任何反馈!


4

“执行鸿沟”概括了用户认为他们需要做的事情,比如订票或查找信息,和系统要求他们做的事情之间的差异。

我总是碰到他们俩!我经常花时间对着我的电脑大喊,“他们为什么用那种方式做这件事?没道理啊!显而易见,他们需要做的就是[在此插入 Josh 的更好设计],”然后我试着冷静下来。看看你是否能在网上找到任何一个海湾,并且意识到当你设计一个 UI 的时候,你需要把你认为系统应该如何工作的想法转化成你的用户能理解的心智模型。当你的用户很容易得到它,那就是好的可用性和好的交互设计。

Image 注意当我们谈到好书的时候,你也应该读一下史蒂夫·克鲁格斯的不要让我想起和罗伯特·莱曼、艾兰·库伯和戴夫·克罗宁的关于 Face 3:交互设计的要点

通用设计

通用设计是近年来包容性设计中最令人兴奋的发展之一。

通用设计可以定义如下:

“产品和环境的设计应尽最大可能为所有人所用,而不需要改造或专门设计。”5

图 9-1 到图 9-7 展示了“通用设计的 7 个原则”,它们是由已故的北卡罗来纳州立大学的罗纳德·梅斯领导的一个由建筑师、产品设计师、工程师和环境设计研究人员组成的工作组于 1997 年开发的。 6 原则的目的是指导环境、产品和传播的设计。根据 NCSU 通用设计中心的说法,这些原则“可以用来评估现有的设计,指导设计过程,并教育设计师和消费者更有用的产品和环境的特征。”


5

6

Image 注意你可能会看到这些原则和 WCAG 2.0 之间的一些相似之处,而且确实有。看看你能认出哪些!通用设计(UD)指南旨在跨越几个领域,从产品设计到信息和通信技术(ICT)和建筑环境。它们是有用的精神食粮,甚至对你的 HTML5 项目也是如此。

Image

***图 9-1。*原则 1:合理使用

以下是这一原则的指导方针:

  • 1a .为所有用户提供相同的使用方式:尽可能使其相同,否则等同使用。
  • 1b .避免隔离或侮辱任何用户。
  • 1c。所有用户都应该能够平等地获得隐私、安全和保障。
  • 1d。让设计吸引所有用户。

Image

***图 9-2。*原则二:灵活使用

以下是这一原则的指导方针:

  • 2a .提供使用方法的选择。
  • 2b。适应右手和左手的访问和使用。
  • 2c。方便用户的准确度和精确度。
  • 2d。提供对用户速度的适应性。

Image

***图 9-3。*原则 3:使用简单直观

以下是这一原则的指导方针:

  • 3a .消除不必要的复杂性。
  • 3b。与用户的期望和直觉保持一致。
  • 3c。适应广泛的读写和语言技能。
  • 3d。根据信息的重要性排列信息。
  • 3e。在任务过程中和任务完成后提供有效的提示和反馈。

Image

***图 9-4。*原则 4:感知信息

以下是这一原则的指导方针:

  • 4a .使用不同的模式(图像、语言、触觉)来重复呈现基本信息。
  • 4b .在基本信息和周围环境之间提供足够的对比。
  • 4c。最大限度地提高基本信息的可读性。
  • 4d。以可描述的方式区分元素(即,使其易于给出指示或方向)。
  • 4e。提供与感官受限者使用的各种技术或设备的兼容性。

Image

***图 9-5。*原则 5:对错误的容忍

以下是这一原则的指导方针:

  • 5a .安排元素以最小化危险和错误。可能的排列包括按最常用的元素或最易访问的元素排序;消除、隔离或屏蔽危险元素。
  • 5b。提供危险和错误的警告。
  • 5c。提供故障安全功能。
  • 5d。在需要警惕的任务中阻止无意识的行动。

Image

***图 9-6。*原则 6:低体力消耗

以下是这一原则的指导方针:

  • 6a .允许使用者保持中立体位。
  • 6b。使用合理的操作力。
  • 6c。尽量减少重复动作。
  • 6d。尽量减少持续的体力劳动。

Image

***图 9-7。*原则 7:接近和使用的尺寸和空间

以下是这一原则的指导方针:

  • 7a .为任何坐着或站着的用户提供对重要元素的清晰视线。
  • 7b .让任何坐着或站着的用户都能舒适地触及所有部件。
  • 7c .适应手和握把尺寸的变化。
  • 7d。为使用辅助设备或个人协助提供足够的空间。

Image 提示html 5 规范确实声称支持“通用设计”你如何在你的项目中做到这一点?当你在构建一个 HTML5 界面的时候,当你已经完成了一个你满意的原型的时候,想想看。回到 UD 原则,看看你的网站是否遵守这些原则。这样做很有趣,也很有教育意义。

参与式设计

Jeffery Rubin(一位有影响力的可用性专家)将参与式设计概括为一种技术,其中设计团队本身可能有一个或多个最终用户。通过让设计者挖掘用户的知识、技能和情感反应,用户被放在了过程的中心。

在实践中,你可能并不总是有足够的资源(无论是财力还是时间)来做这件事,但是如果你足够幸运地在一家财力雄厚的公司工作,探索这个选项可能是值得的。然而,Rubin 警告说,用户可能会被这个过程“消耗”,因为紧密合作的团队可能会陷入某种泡沫——错误地认为一旦团队中的每个人都可以愉快地使用或理解系统,就可以进入黄金时代了!

焦点小组研究

焦点小组研究的目的是在开发过程的早期阶段评估项目的基本概念。它可以用来识别和确认用户的特征,也可以用来验证产品的预期效果。它通常涉及多个参与者。

要探索的概念可以以多种形式呈现给小组,例如纸笔绘图、故事板、PowerPoint 演示、3D 原型和模型等等。这个想法是为了确定这些概念对小组参与者的可接受程度,以及如何改进它们。

焦点小组当然是非常有用的,也是一种很有价值的方式来弄清楚用户想从项目中得到什么。这也是一种有效的方法,可以对 UI 组件进行快速原型测试,或者获得对 HTML5 设计的线框或其他方面的反馈。

调查

调查通常用于了解用户对现有产品或潜在产品的偏好。与焦点小组相比,调查在某些方面是一种更为肤浅的数据收集方式,但它尤其有助于了解更多人的观点。它们可以在任何时候使用,但通常是在产品开发周期的开始使用。

彻底的调查设计非常重要,必须在调查设计中进行大量的思考,以确保问题清晰明确,从而充分利用返回的数据。对你来说,做调查可能不太实际,但作为一种从最终用户那里获取信息的方法,这是值得一提的。如果你在大学校园或有内部网的大型组织中工作,调查是你可以在内部做的事情。

认知预排

认知演练是一种评估用户界面设计的常用技术,特别关注界面支持探索性学习的程度——即,在没有正式培训的情况下首次成功使用。这种评估可以由系统设计者在设计的早期阶段执行,例如,在用户测试可能之前。

早期版本的预演方法依赖于在纸质或电子表格上回答一系列详细的问题。这些可以采取“纸笔评估”的形式,这是一种了解用户对用户界面某些属性的偏好的有用方式,例如菜单或其他控件的组织和布局。

纸笔评估是你界面的字面意思,非常有用,因为设计者可以很快找到关键信息。它们也不贵,并且允许你在任何开发工作开始之前获得一些关于用户界面有多直观的真实反馈。这种技术可以根据需要经常使用,并且可以与原型软件(如 Serena Prototype Composer 或 Axure)结合使用,或者代替它们。

专家评估

专家评估指的是请一位与项目关系不大的可用性专家来评估其可用性。专家应用可用性原则来评估系统的质量和任何潜在的问题。这种类型的评估可以与系统的可访问性审计一起执行,以查看残疾人使用辅助技术(AT)的可用性。

专家可访问性审计

一个可访问性审计测试一个网站或应用是否存在技术上的可访问性问题,比如 WCAG 2.0。从一个独立的角度来看,这是一种非常有效的方式来判断系统的对错。它通常采用建议列表的形式,针对每个 WCAG 2.0 检查点列表。

然而,来自审计的反馈必须被积极地整合到项目中。只有当它作为迭代开发过程的一部分时,这种情况才会发生;如果建议是在最后加上的,那就没有效果。如果使用得当,可访问性审计是最有用的工具之一。然而,通常存在一种最低限度遵从的文化——一种“我们稍后会处理它,我们有审计”的态度,这使得实践变得空洞和无意义。

理想的途径是首先创建一个设计良好的网站,该网站结合了最佳实践,如果可能的话,使用用户的反馈——理想的做法是在项目的不同阶段,或迭代的开发过程中结合用户的反馈。当项目的一个阶段处于稳定状态时,它应该由第三方进行可访问性审计(这对客观性很重要)。在整合了测试结果之后,应该进行用户测试。

用户测试不只是锦上添花,它是成功或失败的严峻考验。

使用角色

在某些情况下,进行用户测试可能根本不可行。这就是使用人物角色有用的地方。一个人物角色是一个特定用户群的品质和属性的精华原型。这些属性是用户体验专家认为可能代表特定用户群(如盲人)的各种品质的模型。因此,他们在周围建立了一个角色。

人物角色使用旨在模拟这群用户使用网站的体验。如果各种人物角色是准确的,那么对他们体验的模拟也可能是准确的。人物角色可以用来证明应用设计的修改是合理的,基于人物角色的感知需求。

构建人物角色

人物角色是从收集的关于目标群体的研究中创建的。这可以来自调查、采访等等。建立代表普通用户的人物角色是可能的。这些不同的组可以包括老年人、年轻人、盲人用户等等。好的人物角色来自从真实用户那里收集的真实反馈。

使用人物角色有用吗?

尽管人物角色被广泛使用,但是很少有经验证据支持使用人物角色可以提高用户界面设计的质量。然而,在 Frontend(一家优秀的爱尔兰用户体验和界面设计公司)的 Frank Long 进行的一项非常有趣的实地研究中,调查了使用人物角色的有效性。这是一项为期五周的实验,参与者是都柏林国家艺术与设计学院的学生。结果表明,通过使用人物角色,产生了具有卓越可用性特征的设计。结果还表明,在设计过程的研究和概念化阶段,使用人物角色提供了一个显著的优势(支持以前没有根据的主张)。

该研究还调查了使用不同的展示方法来展示人物角色的效果,并得出结论,照片比插图效果更好,视觉故事板比纯文本版本更能有效地展示任务场景。

Image 你可以在[www.frontend.com/products-digital-devices/real-or-imaginary-the-effectiveness-of-using-personas-in-product-design.html](http://www.frontend.com/products-digital-devices/real-or-imaginary-the-effectiveness-of-using-personas-in-product-design.html)阅读 Frank Long 的论文全文《真实还是想象:产品设计中使用人物角色的有效性》。

衡量使用人物角色的有效性

龙的研究提供了客观的证据来支持库珀等人(他们的发明者)关于在产品设计过程中使用人物角色的关键主张。使用人物角色似乎加强了设计师对最终用户和用户的任务、目标和动机的关注。人物角色使最终用户的需求更加明确,因此可以引导设计团队的决策更加符合这些需求。这项研究还表明,使用人物角色可以改善团队之间的沟通,促进更有建设性的和以用户为中心的设计讨论。

然而,人物角色的使用并不总是得到赞许。查普曼和米尔汉姆的研究旨在批判性地评估人物角色的使用,他们对人物角色的使用是有效的这一说法表示了关注。他们认为人物角色实际上是有害的,会导致扭曲的和不正确的结论,因此他们是不可靠的。他们问,“这个角色代表了多少用户?”,“这个人物角色与一个群体相关吗?”“人物角色到底是不是一种有效的方法(以及如何验证这一点)?”7

这些都是合理的问题。龙还发现,使用人物角色的插图而不是照片似乎会降低有效性,并减少对插图人物角色的同理心。此外,故事板任务场景的使用比文本版本更有效,有助于更详细的设计解决方案。

Long 的结论是,在产品开发中使用人物角色为以用户为中心的设计提供了几个好处,比如增加了在产品规格阶段纳入以用户为中心的功能的可能性。他提供了一些客观的证据来证明使用人物角色确实有效。

实地研究

现场研究是一个术语,指的是在自然环境中测试产品或界面,这是最理想的。该设置可以是办公室、家庭或任何其他真实反映产品使用方式的环境。现场研究可能或不可能进行,当在产品周期的后期进行时,不应将其视为产品或界面重大问题的指标,而应将其视为一种改进的方法。

传统可用性测试

传统的可用性测试包括随机抽取公众样本或代表性用户样本进行测试,这些用户实际上会使用网络应用或网站。这种类型的测试试图评估用户体验的质量。测试的结果——例如用户是否能成功完成某个任务或一组任务,用户完成任务的易用性,以及测试期间的其他用户反馈和观察——都由测试主持人记录下来。这些记录下来的信息是有价值的,因为它让一个有经验的可用性分析人员能够详细了解在一个特定的用户界面设计中,什么对最终用户有用,什么没用。

尽管传统的可用性测试非常有用,但它通常只能捕获一小部分问题。它并不详尽,但是在测试过程中任何困难都会立即显现出来。一个有经验的可用性专家确切地了解设计或实现是如何导致这些问题的,以及如何解决这些问题。

残疾人用户测试

虽然对没有残疾的人进行用户测试通常会产生许多肯定可以改善用户体验的积极结果,但这些用户通常有更多的标准要求,可能不需要或不使用 at。

因此,让残疾人参与用户测试通常是详细了解界面、应用或网站对使用 AT 的人的可用性的最佳方式。也有许多轻度到中度残疾的人不使用 AT,而是依赖他们的操作系统、浏览器和良好的键盘可访问性的可访问性设置。通过仔细研究残疾用户的体验,可以深入了解您的设计选择和决策如何影响用户体验。


7C . N . Chapman 和 r . P . Milham(2006)人物的新装:反对流行方法的方法学和实践论证,人类因素和人类工程学学会第 50 届年会论文集,第 634-636 页。在线提供:[cnchapman.files.wordpress.com/2007/03/chapman-milham-personas-hfes2006-0139-0330.pdf](http://cnchapman.files.wordpress.com/2007/03/chapman-milham-personas-hfes2006-0139-0330.pdf)

如果你迭代地进行用户测试*——也就是说,让残疾人参与到项目的整个开发和设计周期中——你就能形成一个更加全面的用户体验图,并在早期做出有效的设计决策。*

*#### 正式与非正式用户测试

正式的可用性分析和用户测试让人想起穿着白大褂的严肃科学家在单向玻璃观察屏幕后面做笔记的画面——而测试参与者通过对讲系统或反馈继电器传达命令和任务。当然,这些指令必须以不带任何情感暗示或人性外表的声音给出,以避免测试中的偏见。这些图像,虽然很明显是漫画式的,但却是许多人在听到“观察”、“测试”和“分析”这些词时所想到的。然而,这是一个相当过时的观点,与用户测试领域当前的趋势和习惯不一致。

正式的用户测试与科学方法密切相关。尽管这种方法在某些领域肯定是有效的,但这不是我们在这里所关心的。形式方法与统计分析和控制实验相关联。就对你的 HTML5 项目进行路测而言,我们在这里关心的是更真实的方法非正式用户测试。在这种情况下,测试通常必须快速完成,作为迭代开发周期的一部分(最好的情况下),最坏的情况下,作为项目结束时验证的附加部分。

更非正式的用户测试是有一个测试脚本和一系列事先概述的任务。测试主持人也可能有一种多年来建立起来的关系,在这种关系中,测试主持人和参与者一起做了许多许多测试。

测量用户测试输出

用户测试有一定的输出。这些信息是多种多样的,可以是测试主持人积累的笔记、测试过程中收集的用于以后分析的视频片段、未参与测试的观察者的集体印象等等。一些输出更加有形,例如可以存档并在以后观看的视频。有些不太明显,但仍然非常有价值,比如用户测试可以给观察者留下持久的印象,当他们看到有人使用他们的网站时。

然而,这些不太有形的印象和主观体验可以产生非常真实的输出。如果项目经理看到用户对某个产品界面的实时负面反应,那么产品可能会被丢弃,软件迭代周期可能会被放弃,等等。反过来,当用户说,“是的,这个网站很棒”时,设计师的设计努力和对细节的关注就会开花结果。我可以很容易地找到我需要的信息。我喜欢页面的设计方式。”当被观察的人有残疾时,这种体验会更加深刻。

可用性专家不是通过观察普通的用户体验测试来获得有趣的信息的。用户测试分析真正有趣的方面发生在极端的情况下——包括正面的和负面的。在这里,积极和消极的经历都被放大并变得非常明显,所以通常不会有歧义。这种语言通常不那么中性,因此用户对特定用户界面或应用的印象和感受是毋庸置疑的。

用户测试是如何工作的?

图 9-8 是一个用户测试设施的例子(我在 NCBI 包容性技术中心工作的那个)。该图显示了房间和设备的布局。

Image

***图 9-8。*作者的实验室

用户环境

用户测试参与者(1)坐在受声音控制的测试室内的典型办公室环境中。测试主持人(2)与用户坐在一起,解释任务,做笔记,并严格观察用户的交互。使用带有辅助硬件和软件的标准 PC (3)进行测试。专用的用户测试记录软件,如 Morae,以及不显眼的摄像头和麦克风,捕捉和记录用户测试会话的每个方面,供以后分析。

观察环境

观察者可以在观察室舒适的沙发上实时观看测试。来自用户监视器(6)的视频显示在平板电视(4)上,而来自摄像机和麦克风(7)的第二信号在电视监视器(5)上显示用户的手势、面部表情、身体语言和发声。

通过这些链接,观察者可以看到用户做的和说的一切,以及用户和主持人之间的交互。

测试详情

典型的用户测试由八个独立的用户会话组成,每个会话持续一至一个半小时。测试的使用类型涵盖了广泛的残疾和辅助技术。它还允许我们将年轻和年长的用户与具有不同经验水平的人包括在内。这使得态度和方法的样本更具代表性。图 9-9 显示一名参与者在中心。

Image

***图 9-9。*NCBI 包容性技术可用性实验室中心的用户测试参与者

每个用户执行一组与客户事先商定的实际任务。

这些任务通常包括使用该产品的最常见的任务,以及最关键的任务和测试主持人可能预料会给用户带来问题的任何任务。测试是精心设计和运行的,以产生尽可能真实的用户行为。图 9-10 显示了一名辅导员和一名用户在测试实验室中。

Image

***图 9-10。*NCBI 包容性技术中心实验室的用户测试主持人和参与者

用户测试的基本要素

鲁宾为更多的非正式测试概述了基本方法和标准要素 8 :

  • 开发问题陈述或测试目标,而不是假设。
  • 使用有代表性的最终用户样本,这可能是随机选择的,也可能不是随机选择的。
  • 使用工作环境的代表。
  • 观察最终用户(有代表性的产品)。

可用性测试手册:如何计划、设计和实现有效的测试(威利技术交流图书馆)

  • 由测试监督人(主持人)对参与者进行受控的询问和探查。
  • 收集定量和定性的绩效和偏好指标。
  • 对产品的设计提出改进建议。

前面的几点形成了用户测试核心方面的概要。当我进行一项测试时,我会先与客户交谈,并询问他或她希望我关注的网站核心区域是什么。请记住,您的客户将比您更熟悉这个系统(当然,除非是您构建的!).然后,我根据这些反馈和我自己对网站的测试起草了一个测试脚本,我事先做了这些来识别任何可能的问题区域。然后,我招募患有不同类型残疾的用户,如弱视、失明、行动受限或认知/感官残疾。我还试图混合测试参与者的年龄范围,因为这能给出更好的结果。

Image 注意尽管拥有尽可能多样化的团队很好,但也不要试图做得太多。拥有一个给出良好反馈的更小的团队并进行多次迭代测试是很好的。可用性等实际问题往往是一个大问题,后勤工作可能会很尴尬,因为人们承诺参加,然后退出等等。你只要跟着它走就行了!

当执行测试时,最初我非常清楚不要引导用户,并试图对整个事情非常科学。然而,我很快意识到这并不总是必要或明智的。我不得不面对这样一个事实,整个测试都是人为的和做作的——试图让它不是这样的,或者以某种科学的名义忽视现实情况,在我看来是相当浅薄和没有意义的。当你承认测试是人为的,你让自己和测试参与者都放松下来,你可能会发现你喜欢这个过程。在我看来,这是健康的,可以产生更好的数据。

“为什么?”你可能会问。首先,测试参与者在放松时可能更倾向于诚实。此外,他们会更倾向于冒险和尝试新事物,如果他们紧张,他们可能不会尝试。其中的原因很有趣,我花了很长时间才意识到:用户测试参与者通常希望取悦测试主持人,不希望被视为不能做某事。在对残疾人进行测试时更是如此——他们可能非常害羞,所以你需要意识到这一点,并清楚地解释说他们没有被测试。如果一个人不能执行某项任务,他们可能会觉得自己有问题,这个问题很可能是一个连史蒂夫·霍金都无法理解的可访问性和可用性问题!所以试着放松,甚至玩得开心。值得。如果你对同样的人做更多的测试,你会和他们建立融洽的关系,了解他们的互动模式。如果你放心,那将是对他们的一大帮助。

观察用户测试

观察用户测试,如图 9-11 所示,是获得易访问性和可用性真正含义的第一手理解的最好方法之一。尤其是设计师和开发者,他们可以从观察用户所获得的洞察力中获得巨大的收益。

有些设施有专门的观察室,就像我们的一样。使用宽屏电视和小型视频监视器,客户可以通过远程链接观看和收听用户测试,而不会干扰用户的工作。

Image

***图 9-11。*在 NCBI 包容性技术中心观察室观察用户测试

用户会话的数字视频记录通常用于在测试后回顾会话,并说明关键问题。重点是建立对网站设计如何造成用户困难的理解,以及可以采取什么实际步骤来缓解这些问题。

用户测试的目标和好处

用户测试将在几个方面帮助您的 HTML5 项目。其中一个主要目标是,它将帮助您识别您的站点用户可能存在的问题,并在您上线之前为您提供修复这些问题的机会。

需要记住的一些问题如下:

  • 你的网站既容易学习又容易使用吗?
  • 用起来满意吗?
  • 网站会因为提供用户需要的功能而被用户重视吗?

以下是用户测试的一些好处:

  • 用户测试你的项目并记录结果会给你以后的网站版本一个参考点。
  • 如果从一开始就是一个高质量的项目,那么花费在支持/维护网站上的时间就会减少。因此,从长远来看,你从用户那里获得反馈的努力是值得的。
  • 一个更好的网站会带来更多的销售或更多的使用,以及更少的投诉。
  • 一个更好的网站会让你比你的竞争对手更有优势。

Image 注意有趣的是,在过去的几年里,随着互联网变得越来越普及,消费者获得了更多的选择,对可用性专家服务的需求有了很大的增长。当用户体验的质量决定了你的网站用户将会购买什么和他们将会使用什么服务时,可用性就有了用武之地。

测试的局限性

尽管用户测试无疑是有用的,并且是以用户为中心的设计开发周期的重要部分,但是测试也有一些你应该知道的缺点:

  • **用户测试是人为的环境:**无论你如何分割,用户测试和观察人们使用产品或服务都是人为的。您所看到的只是真实用法的摹本,用户通常不会像在自己的环境中那样行事。观察事物的行为会改变它。
  • **用户测试结果可能并不能真正证明你的 HTML5 网站真的有效:**要做统计显著性测试,你必须做很多。我们掌握的大部分资源都不允许我们这样做。此外,最终用户可能经常会忽略您的站点中非常明显的错误(如果您构建了站点或者是一个有经验的测试服务商),甚至是在较大的测试样本中。
  • **你的用户测试参与者通常并不真正代表你的目标受众:**即使你非常小心地选择合适的人,测试结果也可能从一开始就有偏差,因为你可能有太多更高级的用户或太多只有基本数字素养的用户。找到正确的平衡通常非常困难。同样,要做更能代表更广泛受众的测试,你需要招募比大多数开发人员实际做的更多的人。
  • 用户测试总是最好的技术吗?这是一个重要的问题。例如,可用性评估形式的专家评估可能是您的项目的最佳方法。首先可能需要专业知识来使用系统,所以在这种情况下,用新手用户进行测试并不理想。
数字素养

一个反复出现的问题是,一个人对他使用的 at 以及一般的网络和技术的流利程度。在测试过程的早期,如果你没有经验,你可能会看到用户有问题,并认为这是用户界面或网站设计的错误。但是是吗?你需要确定。这就是使用一个有经验的测试主持人的好处——特别是,使用一个深刻理解 AT 如何工作的人。周围没有很多,但如果你能找到他们,他们值得一起工作。这是因为在理解和分析您的测试结果时,这样的专家为您的项目带来的知识是非常宝贵的。你必须记住,你需要根据这些结果做出设计决策。

那么,对我来说,评估我的 HTML5 项目的最好方法是什么呢?

正如您从我们所介绍的内容中所看到的,有各种各样的用户评估方法可供使用。即使对于可用性专家来说,也很难真正了解最适合任何给定项目的用户评估方法——用户测试、焦点小组、原型或其他方法。以下是一些主要问题:

  • **评价者效应。**这是指不同的测试主持人或评估者对相同的数据集得出不同的结果。
  • 在应用可用性评估技术时缺乏科学的严谨性。这大大削弱了在用户测试或其他可用性评估方法中收集的大量用户数据的可靠性。
  • 普遍缺乏可用于比较评估方法的适当标准或指标。

简而言之,没有“放之四海而皆准”的方法,所以您必须根据您从测试中需要的东西和您拥有的资源来处理您的项目。随着时间的推移,它会变得更容易,随着经验的积累,你会学会忽略什么,注意什么。

迭代设计流程

可用性圈子里也有很多关于响应或迭代设计过程的重要性。(你可能已经注意到这一章中提到了这一点。然而,在实践中,对于如何实现这一目标,人们往往很少达成一致。

Image 注意迭代设计过程的本质是在构建的每个阶段尽可能早地包含用户的参与。如果你将项目分成三个阶段——比如初始阶段、原型阶段和最终阶段,理想情况下,每个阶段的可用性测试结果都会反馈到每个连续的阶段。这导致网站的核心是来自用户的真实反馈。

可用性是新的经济学吗?

有一个老笑话,如果你问四个经济学家同一个问题,你会得到五个答案。在某种程度上,它在可用性领域是相似的。即使是最有经验的专业人士,看着同样的数据,也常常会对什么是关键问题做出截然不同的分析。经常有这样的情况,他们很少遇到类似的问题。

然而,这并不是说本章讨论的以用户为中心的设计过程没有用。是的,但这不是一门精确的科学。如果你想冒险开始使用这些方法,我强烈建议你去尝试。你会犯错误,但是相信你的直觉,从错误中学习。建立人性化的技术来帮助人们做他们想做的,或者实际上需要在线做的事情是非常值得和令人满意的。

注意我在这一章给出的许多建议都是基于我自己多年来做用户测试的经验,并且受到了像唐纳德·诺曼,特别是杰弗瑞·鲁宾等人的影响。我强烈推荐鲁宾的书可用性测试手册:如何计划、设计和进行有效的测试作为进一步的阅读。

结论

本章介绍了许多以用户为中心的设计过程和方法。你应该随意挑选适合你特殊需要和环境的东西。没有“一刀切”的方法。然而,我强烈建议您开始尝试尽可能地将它们合并到您的 HTML5 项目中。

对我来说,最具讽刺意味的事情之一是,作为一个多年来一直在对涉及残疾人的网站和应用进行用户测试的人,让开发人员会见和观察残疾人使用他们的系统这一简单的行为往往非常强大。开发者通常会有一个顿悟。意识到所有关于可访问性、可用性和各种指南的应用都不是空洞或深奥的练习。你我做出的好的和(事实上)坏的编码和设计决策会对人们的生活产生影响,这种影响可能是我们最初没有能力感知的。*

十、工具、提示和技巧:评估可访问的 HTML5 项目

在这一章中,你将看到一些可用的工具和技术来帮助你的可访问的 HTML5 站点达到最好。通过花一点时间使用我将在这里概述的一些工具,您可以避免一些常见的陷阱,并测试您的工作(或者其他人的工作)以了解其可访问性水平并评估其可用性的一些方面。

Image 注意好消息是有很多你喜欢的浏览器的插件;坏消息是你最喜欢的浏览器有很多插件!在这一章中,我将概述一些我最熟悉的或者我在为我的客户对网站进行日常评估时使用的方法。

我们将讨论诸如验证自动化可访问性检查等主题,并且您将看到如何在测试中使用屏幕阅读器(包括如何做和如何不做)。您还将看到如何进行快速的“游击式用户测试”(读完上一章后,您应该还记忆犹新)。此外,如果您没有设备与真人一起进行用户测试,本章将展示一些简单的模拟技术,可能有助于您了解残障人士可能会如何体验您的网站。

对开发者有用的工具

接下来我们将看看一些不可或缺的工具,你可以用它们来提高你的 HTML5 项目的可访问性。

Chris Pederick Web Developer 工具栏

我很遗憾地说,您将看到的第一个工具不再由开发人员维护。然而,它是最好的之一。它是 Firefox 的 Chris Pederick Web Developer 工具栏,如图 10-1 所示。

Image

***图 10-1。*Firefox 中的 Web 开发者工具栏

这是一个优雅的工具,可以用来测试页面是否存在 HTML 标题、未标记的表单控件、缺少@alt的图像以及许多其他非常有用的与可访问性相关的东西。它的上一个官方版本是针对 Firefox 4 的,也有一个 Chrome 版本。话虽如此,这个插件仍然可以在我使用的 Firefox 9 的一个实例中工作,但它可能会有问题。我希望将来会发布一个更新的插件,它可以在新的浏览器上工作。它值得一提纯粹是因为它太好了。更多详情,敬请关注[chrispederick.com/work/web-developer](http://chrispederick.com/work/web-developer)

WAT-C 网页可访问性工具栏(Internet Explorer 和 Opera)

Web Accessibility Tools Consortium(WAT-C)开发了这个工具,Jim Thatcher(他开发了第一个屏幕阅读器)将其描述为“近年来在可访问性方面发生的最好的事情”。由的 Steve Faulkner 和 WAT-C 的 Jun 开发的 WAT-C 网页可访问性工具栏如图图 10-2 所示。

Image

***图 10-2。*Internet Explorer 中的网页可访问性工具栏

这是一个很好的工具,既可以识别网页的各种组件,也可以让您访问页面内容的其他视图。您可以使用它来获得结构(或缺少结构)的概述、表格标记的好坏(例如,它们是否有表格标题、合适的标题或摘要数据)等等。Web 辅助功能工具栏提供英语、法语、意大利语、德语和中文等语言版本。WAT-C 一直致力于开发其工具的新版本——在 WAT-C 网站[www.wat-c.org/tools](http://www.wat-c.org/tools)上可以找到完整的版本。

色彩对比分析仪

另一个我经常使用的优秀工具是色彩对比分析仪,如图 10-3 所示。

Image 注意我第一次看到这个工具是作为火狐浏览器的插件,最初是由 Gez Lemon(TPG Juicy Studio 的)开发的。

我在 Mac 上(大部分时间),所以我喜欢使用该平台自带的工具(尽管我也在 PC 上做了很多测试)。当 TPG 的 Cédric Trévisan 为 Mac 开发了色彩对比分析器时,我真的很高兴,这是一个非常好的工具,我用来检查用户界面的前景和背景色。它可以告诉我这些颜色对视力受损的人来说是否有问题。

该工具检查前景色和背景色的组合,以确定它们是否提供了良好的颜色可视性。它还包含创建某些视觉条件(如色盲)模拟的功能。

颜色可见度的概念是基于万维网联盟(W3C)提出的对比度算法。

Image 注意对比度是 W3C 的一个建议,用于帮助色盲或其他视觉障碍的人判断两种颜色之间的对比度。

Image

***图 10-3。*色彩对比分析仪(Mac 版)

您可以使用该工具来帮助确定网页上文本的易读性以及基于图像的文本表示的易读性。当您想要查看您的内容是否符合 Web 内容可访问性指南(WCAG)时,它特别有用。例如,WCAG2.0 准则 1.4 解决了使内容可区分的问题,规定您应该执行以下操作:

“让用户更容易看到和听到内容,包括将前景与背景分开。”1

准则 1.4.3 对比度(最低)规定如下:


1

文本和文本图像的视觉呈现对比率至少为 4.5:1,以下情况除外(AA 级):

  • ***大尺寸文字:*大尺寸文字和大尺寸文字的图像具有至少 3:1 的对比度。
  • ***附带:*作为非活动用户界面组件的一部分的文本或文本图像,纯装饰性的,任何人都看不见的,或者是包含其他重要视觉内容的图片的一部分的,没有对比度要求。
  • ***标识:*作为标识或品牌名称一部分的文字没有最低对比度要求。

准则 1.4.6:对比(增强)指出:

文本和文本图像的视觉呈现的对比度至少为 7:1,以下情况除外:(AAA 级):

  • ***大尺寸文字:*大尺寸文字和大尺寸文字的图像的对比度至少为 4.5:1。
  • ***附带:*作为非活动用户界面组件一部分的文本或文本图像,它们是纯装饰性的,对标识不可见:作为标识或品牌名称一部分的文本没有最低对比度要求。

色彩对比分析仪非常有用,可以帮助你测试你的色彩对比是否足以满足这两点。事实证明,这是一种为你提供即时反馈的聪明方式,正如你在图 10-4 中看到的。

Image

***图 10-4。*色彩对比分析仪反馈(Mac 版)

WAVE 是我目前最喜欢的检查网页可访问性和快速发现潜在问题的工具。这是我这些天反复提到的一个问题。这是一个由 WebAIM 团队开发的免费可访问性评估工具(你可以在优秀的[www.WebAIM.org](http://www.WebAIM.org)网站上探索他们的工作)。WebAIM 站点本身是一个与可访问性相关的极好的资源,它已经成为全世界可访问性社区的中心,包括从业者、专家和新手。我强烈建议你把浏览器指向那个方向。

那么 WAVE 是做什么的呢?这个想法是 WAVE 被用来帮助人们进行网页可访问性评估。WAVE 并没有提供复杂的技术报告,而是通过内嵌的图标和指示器来显示网页的可访问性。

有几种不同的方法可以让页面摆动。您可以使用网站并输入 URL、上传文件或直接输入 HTML 代码。图 10-5 是 WAVE 网站的屏幕截图。

Image

***图 10-5。*浪潮首页【wave.webaim.org】??

如果您有一些本地文件需要评估可访问性,您可以下载并安装 Firefox 的 WAVE 插件,还有一个 Dream Weaver 扩展。还有其他选项,比如通过链接或 WAVE 按钮将 WAVE 添加到网页中。你可以在 WAVE 中创建快速链接和书签来自动处理页面,也可以在其他工具中实现 WAVE,比如 Google toolbar。

我的偏好是使用 WAVE 工具作为 Firefox 的插件。这种方法如图 10-6 所示。

Image

***图 10-6。*火狐浏览器的 WAVE 插件

对我来说,WAVE 的伟大之处在于,我发现它以一种非常优雅的方式运行。如果你有一个网站,比如我自己的 NCBI 包容性技术中心(CFIT),你可以看到 WAVE 评估前后的图片。图 10-7 是应用 WAVE 之前的页面。

Image

***图 10-7。*CFIT 网站首波

稍后,通过添加这个 URL 到 WAVE 工具,你会看到如图 10-8 所示的结果。这显示了 WAVE 如何评估页面,从而为您提供出色的视觉反馈,突出显示网站的错误和可访问的方面。

Image

***图 10-8。*CFIT 网站后波

所以我的工作主页很健康。您可以看到该工具添加了有用的图标来指示页面上出现标题的位置,以及一些我添加的 null @alt 文本。波形工具还可以让您更详细地查看页面的结构轮廓。当轮廓选项被激活时,波形工具显示如图图 10-9 所示的页面。

Image

***图 10-9。*波浪页面轮廓特征

Image 注意该工具还有其他有用的选项,比如能够浏览结构/顺序选项,或者只查看文本。最常见的选项是激活错误、功能和警报。这个选项给了你确切的答案,只做罐头上说的事情。

在一个可能有一些可访问性错误的页面上测试错误、功能和提醒选项怎么样?通过 WAVE 工具运行Irishtimes.com网站,你会得到如图 10-10 所示的结果。公平地说,从可访问性的角度来看,该网站实际上并不太差,但总有改进的空间。

Image

***图 10-10。*在 Irishtimes.com 主页上使用 WAVE

您可以看到 WAVE 工具已经检测到 15 个可能的可访问性错误。这些是通过评估工具嵌入页面的真正有用的小图标引起您的注意的。

Image WAVE 也向你展示了你网站的优点!可能有问题的是红色图标。

你可以看到爱尔兰时报网站上的搜索框区域需要注意,可能会有问题,所以让我们再深入探讨一下。图 10-11 显示了鼠标悬停在图标上时出现的错误细节。

Image

***图 10-11。*将鼠标悬停在错误上查看更多详细信息

将鼠标移动到图标上,你会得到更多关于潜在问题的信息。从图 10-11 中可以看到,搜索<input>文本框缺少一个合适的标签。没有标签使得屏幕阅读器用户更难知道<input>是干什么的。所以这很重要。这种能够快速发现问题区域的简单方法使得 WAVE 工具非常有用和有效。

你可以通过点击工具栏上的图标键按钮找到 WAVE 使用的图标的解释。这样做将得到如图图 10-12 所示的图标图例,它概述了用于错误和警报(如 HTML、脚本相关和媒体警报)的图标。通过点击这个按钮,你还可以看到一个网站的结构和语义元素,以及一些辅助功能。

Image

***图 10-12。*波浪图标索引

Image 提示我非常喜欢 WAVE 的一点是,它快速实现了对一些 WAI-ARIA 角色、状态和其他项目的支持。使用 WAVE 也能轻松检测到这些,这真是太棒了。

萤火虫

“你必须使用的真正有用的工具”皇冠上的另一颗宝石是 Firebug。你可以在图 10-13 中看到公司网站的主页。

Image

图 10-13。前往 www.getfirebug.com。现在!

这个工具真的是一个改变游戏规则的工具,当我第一次看到它的时候,我非常高兴。它有很多有用的东西值得推荐。

Firebug 是一个浏览器插件,允许你编辑和调试网页中的 CSS、HTML 和 JavaScript。您可以在 Firebug 中查看和编辑您的代码。您可以检查您自己的代码(以及其他人的代码)来帮助您改进您正在构建的内容,并对其他人的工作方式进行逆向工程。Firebug 还有其他很棒的特性,可以用来加速 JavaScript 运行时和调试 JavaScript。您可以使用它来检查 HTTP 头数据并进行 XMLHttpRequest 监控。我可以继续说它有多棒,但我不会。只要把你的浏览器指向 getfirebug.com/,自己检查一下。

浏览器中的工具

注意,Safari ( 图 10-14 )和 Opera ( 图 10-15 )等浏览器都内置了 DOM 和 CSS 检查工具。你使用什么最终取决于你的偏好和你喜欢的工作方式。

Image

图 10-14。 Safari 网页检测工具

Image

***图 10-15。*蜻蜓歌剧院

自动化可访问性评估工具

实际上有许多自动化的辅助工具。在阅读了杰弗瑞·泽尔德曼的《用网络标准进行设计》一书(??)(新骑手出版社,2009 年)和乔·克拉克的《建立可访问的网站》(??)(新骑手出版社,2002 年)之后,我使用的第一个工具是 A-Prompt 和 A-Checker。两者都是由多伦多大学的适应性技术资源中心(ATRC)开发的。

一个相当全面的自动化可访问性工具列表,“Web 可访问性评估工具的完整列表”,可在[www.w3.org/WAI/RC/tools/complete](http://www.w3.org/WAI/RC/tools/complete)获得。实际上,这些工具是各种各样的,您在项目中使用什么实际上取决于个人偏好。

您可能会发现这些工具的输出很难解析。当我开始对网页可访问性感兴趣时,对我来说最大的挑战是知道什么是严重错误,什么不是。最后,我警告你不要过度依赖或热衷于这些工具的输出。对网站进行专家评估,或者,理想情况下,对残疾人进行用户测试,可能会让你发现问题并不严重。话虽如此,像 WAVE 这样的工具对我来说是赢家,因为它们非常直观和简单,并且非常适合我自己的工作流程。您可能会发现,如果您在非常大的站点上工作,企业级解决方案会满足您的需求。当您使用这些工具(大的或小的)时,我建议您仅将其作为总体评估套件的一部分来使用,而不要将它们的输出视为真理。理想情况下,在检查可访问性和可用性时,你应该使用多种方法的组合,因为一个熟练的可访问性专家将能够发现误报,并以软件无法做到的方式解读问题的细微差别。

Image 注意一些自动化的可访问性检查器有 lite 版本,可以免费使用,如果需要,您可以选择升级订阅以获得更多企业级解决方案。

想要检查可访问性 API 吗?尝试 AccProbe 或 Inspect32

如果你想获得更多关于一个控件如何暴露给一个可访问 API 的细节,AccProbe 和 Inspect32 是两个有用的工具。这些工具执行简单但有用的任务,比如公开 HTML 元素的属性(比如它的名称、角色和状态)。

Inspect32 已经存在一段时间了,它专注于 HTML 组件的可访问性相关属性。

与 Inspect32 类似的其他工具是更新的 AccEvent(或“可访问事件观察器”)。AccEvent 允许开发人员验证应用的 UI 元素在发生 UI 更改时是否会引发正确的 Microsoft UI 自动化和 Microsoft Active Accessibility 事件。例如,当焦点改变时,或者当网页组件具有一些属性或状态改变时,可以发生许多改变。

Image 注意上述工具是微软 Windows SDK 的一部分。

AccProbe 是一个独立的 Eclipse 富客户端产品(RCP)应用,它提供了 Microsoft Active accessible(MSAA)或 IAccessible2 层次结构的视图,公开了该应用或文档的可访问对象的属性。它还可以作为事件监视器来跟踪由这些可访问对象触发的事件。

开发人员应该将 Microsoft Inspect32、AccExplore 和 AccEvent 等工具的功能结合到一个易于使用的应用中,以进行可访问性测试和调试。更多信息见[accessibility.linuxfoundation.org/a11yweb/util/accprobe/](http://accessibility.linuxfoundation.org/a11yweb/util/accprobe/)

对于 UIAutomation API 测试,可以使用 UISpy ( [msdn.microsoft.com/en-us/library/ms727247.aspx](http://msdn.microsoft.com/en-us/library/ms727247.aspx))。UISpy 使开发人员能够探索、查看和询问页面内容的结构、属性值等。它对于检查 UI 自动化事件信息、元素是否可导航以及它是否可以接收键盘焦点等非常有用。

Image IBM 的 Michael Squillace 从盲人用户使用这些工具的体验角度写了一篇有趣的文章。他的文章“编写可访问的辅助工具”可以在[www-03.ibm.com/able/resources/accessible_tools.html](http://www-03.ibm.com/able/resources/accessible_tools.html)找到。

残疾模拟工具:aDesigner

你可以研究一些残疾模拟工具,特别是 aDesigner。使用这些工具,您可以了解网页对于盲人或弱视者的可访问性和可用性。

Image [www.eclipse.org/actf/downloads](http://www.eclipse.org/actf/downloads)得到一个设计者。

我对这些模拟工具有着复杂的感觉,因为当你做用户测试时,你无法击败直接从真实的人那里获得反馈。然而,这并不总是可能的。我的观点是,模拟工具是用户测试可怜的表亲;然而,如果这些工具能够帮助您更好地了解残障人士的需求,并帮助您识别设计中可能存在的问题,那么它们就已经完成了工作,是值得的。

游击队用户测试

这就是我们在第九章中提到的“使用你所拥有的 DIY 朋克摇滚方法”进行用户测试。在这里,你可以使用你周围的人(年龄、计算机知识水平越多样化越好,如果他们同意的话,还有残疾同事,等等),以及使用任何你可以乞求或借用的设备或开源软件,对你的网站或原型进行一些快速和肮脏的用户测试。如果你能用手持摄像机录下整个过程,那就更好了。

享受这些非正式的会议,随着时间的推移,你会发现它们很有用。如果你在运行这些测试时很放松,你的用户会发现这一点,也会放松并给你好的反馈。您还会发现,您快速提出“测试脚本”(概述一些任务)并发现可能的可用性失败的能力将会提高。玩得开心,不要害羞!人们喜欢参与进来,觉得自己在提供帮助。不用担心科学或者太正式。根据我的经验,即使最好的用户测试环境也完全是人为的。承认这一点,你会得到更好的结果。

验证

通过 W3C 验证器的代码验证(在[validator.w3.org](http://validator.w3.org)可用,如图图 10-16 所示)是检查你的文档是否符合特定语法风格的一种方式。这可能是 HTML、CSS、XHTML、MathML 等的一个版本。

Image

***图 10-16。*W3C 验证器

在我进入可访问性领域的早期,我喜欢验证器。这似乎是一个给你反馈的工具(完全无法理解,但仍然是反馈),你可以用它来帮助网站变得更容易访问。此外,如果您正在评估网页的可访问性,这是一个可以用来向您的客户展示必须修复的错误的资源。许多对可访问性或 web 开发知之甚少的人开始求助于 it 来测试他们的网站的可访问性。如果你看到红色的小 x(如图图 10-17 所示),就会有抱怨,必须尽快修复!

Image

***图 10-17。*W3C 验证者发现的样本验证错误

但是它们真的需要尽快修复吗?这些错误严重吗?你如何区分什么是严重问题,什么不是?“一知半解是件危险的事情”这句格言跃入脑海。真正缺乏对验证器是什么(不是什么)的认识给每个人都造成了困惑。我认为它以一种几乎适得其反的方式被依赖,因为这个工具让一个人很容易成为验证狂热者。您可以躲在验证器后面,掩盖您自己对真正的可访问性问题的知识的不足。事实是,在验证器和可访问性之间没有一对一的映射。因此,尽管你可能认为验证等同于 11y,但事实并非如此。实际上,仅仅因为您的页面通过了验证器并不意味着它是可访问的。没有通过验证器也不意味着您的页面不可访问。

验证器检查您的页面内容是否符合您在 DOCTYPE (DTD)中定义的语法。它运行算法来检查您是否坚持了该语言规范中定义的最佳实践。这当然非常有用,验证器可以帮助处理格式良好性,并指示页面是否更容易被访问。但是,这种可能性只是一种概率,而不是确定性。因此,试着按照它的意图对待验证器:作为评估文档一致性的一种方式,而不是作为可访问性检查器。

层叠样式表

你可能已经注意到,这本书并没有涉及很多 CSS3。这真的是故意的。有许多关于这个主题的优秀书籍和在线教程可以为您提供关于 CSS3 的最新提示和技术。这本书关注的是 HTML5 和 WAI-ARIA 提供的辅助技术(at)的语义,比如屏幕阅读器。CSS 不提供这些,并且在不同的层中操作。

然而,使用 CSS 通过确保足够的颜色对比度来帮助您的页面内容适合有视觉障碍的人是一个很大的帮助,同时使用 CSS 来确保您的文本可以通过使用相对字体大小(em 或%)从键盘上调整大小。

CSS3 一个受欢迎的飞跃是它更复杂的排版。使用媒体查询来调整页面内容也很简单。然而,有一些效果我就是不喜欢,比如令人恶心的 CSS 变换,网页现在可以飞入和飞出你的浏览器,或者上下移动,除了“你现在可以这样做了!”此外,CSS 提供的手风琴式菜单过于跳跃、动态(以一种糟糕的方式),或者聪明到几乎无法使用。这些都被我否决了。小心使用这些东西。一点点克制不会伤害任何人。

模拟演习

正如在第一章中提到的,像残疾人一样体验你的网页内容的一个好方法是关闭你浏览器中所有的铃铛和哨子。本节提供了一些简单的练习,如果您不能正常使用某些功能,您可以使用这些练习来感受一下访问网页的感觉。它们试图让你设身处地地为他人着想,关闭浏览器中许多你可能认为理所当然或不假思索就使用的功能。

模拟练习 1:简单的浏览

为了给用户提供简洁的体验,我建议您在选择的浏览器中关闭以下选项:

  • 样式表
  • 形象
  • 声音
  • Java Script 语言
  • 爪哇
  • 支持 Flash/Silverlight
  • 弹出窗口

您不必一下子完成所有这些工作,但是这样做肯定可以帮助您了解页面内容的核心,并体验对于残障人士来说有限的浏览体验是什么样的。

使用 NoScript 阻止 JavaScript/Java 和 Flash 内容

火狐的一个有用插件是 NoScript,如图图 10-18 所示。虽然它的主要用途或目的是为了增加安全性,但它可以很好地用作简单浏览体验的一部分。它易于安装和使用。作为模拟练习,这可能很有用,因为您可以体验 JavaScript 驱动的菜单或窗口小部件的行为,如果它们是以不会优雅地降级的方式编码的话。

Image

图 10-18。 NoScript 在行动

禁用弹出窗口

对于有认知障碍的人来说,弹出窗口可能会让人迷失方向。它们既令人困惑又让人分心,因此很难理解正在发生的事情。对于没有视力的用户来说,这也是一个问题,因为盲人用户在输入数据时可能不得不在弹出窗口和主浏览器窗口之间切换。或者在数据输入的位置和页面状态之间可能会有一个断开。对于更高级的计算机用户来说,除了可用性影响之外,这可能不是一个大问题,但是对于新手用户来说,这可能会让人迷失方向。视力低下的人可能不会意识到弹出窗口的存在。他们可能看不到弹出窗口。一个经验法则是,如果有<input>控件和类似的东西需要用户登录并执行其他类似的任务,只要将它们包含在主浏览器窗口中。尝试完全避免弹出窗口是一个好习惯,当然也要避免产生许多实例或浏览器窗口。这也意味着如果可以的话,你真的不应该在新的浏览器窗口/实例中链接到外部网站。但是,如果你必须这样做,你应该通过在你的链接文本中包含通知“[在新的浏览器窗口中打开]”或类似的内容来通知用户这将会发生。

不用鼠标工作

现在我要你扔掉你的鼠标。

然后像往常一样浏览网页,看看你是如何预订演唱会门票的!浏览一些你熟悉的网站是个好主意(从一个新的角度来看它们),然后浏览一些你以前没去过的网站。

每次尝试 30 分钟左右,你应该会很好地了解网络对许多不同残疾的人来说是什么样的,这些人依赖键盘,或者无法访问 Flash 内容,或者关闭了 JavaScript(无论出于什么原因),等等。

这个简短的实验应该提供足够的思考资料。你还会发现简单的浏览是发现可能问题的好方法。

模拟练习 2:关闭显示器并使用屏幕阅读器

为了真正模拟和理解盲人屏幕阅读器用户的网络,您可以尝试使用屏幕阅读器进行浏览。如果你没有使用屏幕阅读器的经验,这不是一件容易的事情,并且需要一定的决心来坚持下去。屏幕阅读器是一个复杂的应用。在你启动这个软件之前,我建议你仔细阅读它(大多数都有快速入门指南),并坚持一些基本的浏览。如果你有苹果电脑。您已经安装了优秀的 VoiceOver,我建议您花时间使用它。它可以同样有趣和令人沮丧,以及启发。如果你用的是个人电脑,可以从自由科学网站下载 JAWS 的演示,或者你可以试试像 NVDA 这样的免费选项。他们都表演类似主题的变奏曲。

Image 注意JAWS 的演示选项运行 40 分钟,这是你试驾屏幕阅读器时学习的好时机。 2

您应该尽可能多地使用您选择的屏幕阅读器进行练习。如果您确实需要帮助,我建议您联系当地的视力障碍者服务提供商。他们会很乐意帮忙的。这也是一个了解盲人和理解他们浏览策略的好方法。

对于您的早期屏幕阅读器路测,我推荐一些基于任务的简短会议。例如,专注于网站的某个方面,并尝试做一些类似购买音乐会门票的事情,如前所述。这将把你的注意力集中在网站的一个方面(比如表单的可访问性),并给会议一些结构。当你使用屏幕阅读器浏览网页时,它可能会让你感觉不那么无处不在。


2

Image 注意如前所述,屏幕阅读器用户有不同的浏览策略和数字素养水平。记住这一点非常重要。尽管你自己的测试既令人沮丧又有趣,但是它不能代替那些真正失明并且确实需要使用屏幕阅读器的人的用户测试。如果你有视力,心理也会有所不同——当你感到沮丧时,你可以选择打开显示屏或拿起鼠标。无论你在测试中变得多么熟练,你的测试只是真实经验的一个影子。

结论

这一章标志着这本书的结束。我真的希望你学到了一些东西。可达性实际上是一个连续体——一条不断发展的线,而不是一座有待征服的山峰。尽你所能,人们会感激你的。最后,不要羞于加入可访问性社区来学习更多并分享你所知道的。全世界有一个充满活力的网络社区,由热心的人组成,他们乐于分享专业知识和知识,努力让网络成为一个对每个人都更好、更包容的地方。

十一、附录 A:WCAG 2.0 客户端脚本技术

  • SCR1:允许用户延长默认时间限制
  • SCR2:使用冗余键盘和鼠标事件处理程序
  • SCR14:使用脚本使不重要的警报可选
  • SCR16:提供一个脚本,警告用户时间限制即将到期
  • SCR18:提供客户端验证和警报
  • SCR19:在 select 元素上使用 onchange 事件而不导致上下文的更改
  • SCR20:使用键盘和其他设备特定的功能
  • SCR21:使用文档对象模型(DOM)的函数向页面添加内容
  • SCR22:使用脚本控制闪烁,并在 5 秒或更短时间内停止闪烁
  • SCR24:使用渐进式增强应用户请求打开新窗口
  • SCR26:将动态内容插入到文档对象模型中,紧跟在其触发元素之后
  • SCR27:使用文档对象模型重新排序页面部分
  • SCR28:使用可展开和可折叠的菜单绕过内容块
  • SCR29:向静态 HTML 元素添加键盘可访问的操作
  • SCR30:使用脚本更改链接文本
  • SCR31:使用脚本更改具有焦点的元素的背景色或边框

1 版权所有 2008-2011 W3C(麻省理工学院、ERCIM、Keio),保留所有权利。W3C 责任、商标和文档使用规则适用。

  • SCR32:提供客户端验证并通过 DOM 添加错误文本
  • SCR33:使用脚本滚动内容,并提供暂停它的机制
  • SCR34:以随文本大小缩放的方式计算大小和位置
  • SCR35:通过使用锚和按钮的 onclick 事件使操作键盘可访问
  • SCR36:提供一种机制,允许用户在静态窗口或区域中显示移动、滚动或自动更新的文本
  • SCR37:以独立于设备的方式创建自定义对话框

SCR1:允许用户延长默认时限

描述

这种技术的目的是当脚本提供具有默认时间限制的功能时,通过提供一种延长时间的机制来允许用户延长默认时间限制。为了允许用户请求更长的时间限制,脚本可以提供一个表单(例如),允许用户输入更长的时间限制或指示需要更多的时间。如果用户被警告时间限制即将到期(参见“SCR16:提供一个警告用户时间限制即将到期的脚本”),可以在警告对话框中使用该表单。用户可以将时间限制延长到默认时间限制的至少 10 倍,方法是在表单中输入一个值来指示需要多长时间,或者重复延长时间限制。

例子

网页包含当前的股票市场统计数据,并设置为定期刷新。当在第一次刷新之前警告用户时,向用户提供延长刷新之间的时间段的选项。

在在线国际象棋游戏中,每个玩家都有完成每一步棋的时间限制。当玩家被警告该移动的时间快到了时,用户可以选择增加时间限制。

SCR2:使用冗余的键盘和鼠标事件处理程序

描述

这项技术的目的是演示如何使用与设备无关的事件来改变装饰图像,以响应鼠标或焦点事件。当鼠标移动到页面上某个元素的顶部或远离该元素时,使用onmouseoveronmouseout事件来更改装饰图像。此外,当元素获得和失去焦点时,使用onfocusonblur事件来改变图像。

清单 A-1 中的示例在锚元素前有一个装饰图像。当用户将鼠标放在锚点标签上时,锚点前面的装饰图像会发生变化。当鼠标离开锚点时,图像会变回其原始版本。当用户将键盘焦点放在锚元素上时,也会出现同样的图像变化效果。当接收到焦点时,图像改变;当失去焦点时,图像会变回原样。这是通过将onmouseover、、onmouseoutonfocusonblur事件处理程序附加到锚元素来实现的。事件处理程序是一个名为updateImage()的 JavaScript 函数,它改变图像的src属性。响应onmouseoveronmouseoutonfocusonblur事件调用updateImage()

每个图像都有一个唯一的 Id。这个惟一的 ID 和一个布尔值一起被传递给updateImage(),该布尔值指示要使用哪个图像:updateImage(imgId, isOver);。当鼠标在锚元素上或者它有焦点时,true的布尔值被传递。当鼠标离开锚元素或失去焦点时,会传递一个false值。updateImage()函数使用image id加载图像,然后根据布尔值更改src属性。注意,由于图像是用于装饰目的,所以它有一个空的alt属性。

Image 注意最好使用大小相似的图像,并在图像元素上指定高度和宽度属性。这将防止在更新图像时对页面布局进行任何更改。此示例使用大小相同的图像。

***列举 A-1。*交换图像

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  <html lang="en">  <head>  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  <title>Changing Image Source in a Device Independent Manner</title>  <script type="text/javascript">  /* This function will change the image src of an image element.   * param imgId - the id of the image object to change   * param isOver - true when mouse is over or object has focus,   *                false when mouse move out or focus is lost  */  function updateImage(imgId, isOver) {    var theImage = document.getElementById(imgId);    if (theImage != null) { //could use a try/catch block for user agents supporting at least![Image](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/1ad6f730a3214ffaab4ecf7831034b09~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5biD5a6i6aOe6b6Z:q75.awebp?rk3s=f64ab15b&x-expires=1774271284&x-signature=ZV6h%2FkRh7nFoh4IO4VrVxeWUHIA%3D)  JavaScript 1.4                            // These browsers support try/catch - NetScape 6, IE 5, Mozilla,![Image](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/1ad6f730a3214ffaab4ecf7831034b09~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5biD5a6i6aOe6b6Z:q75.awebp?rk3s=f64ab15b&x-expires=1774271284&x-signature=ZV6h%2FkRh7nFoh4IO4VrVxeWUHIA%3D)  Firefox       if (isOver) {         theImage.setAttribute("src","yellowplus.gif");       }       else {         theImage.setAttribute("src","greyplus.gif");       }    }  }  </script>  </head>  <body>  <p>Mouse over or tab to the links below and see the image change.</p>  <a href="http://www.w3.org/wai" onmouseover="updateImage('wai', true);"![Image](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/1ad6f730a3214ffaab4ecf7831034b09~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5biD5a6i6aOe6b6Z:q75.awebp?rk3s=f64ab15b&x-expires=1774271284&x-signature=ZV6h%2FkRh7nFoh4IO4VrVxeWUHIA%3D)  onfocus="updateImage('wai', true);"    onmouseout="updateImage('wai',false);" onblur="updateImage('wai',false);">  <img src="greyplus.gif" border="0" alt="" id="wai">    W3C Web Accessibility Initiative</a> &  <a href="http://www.w3.org/International/" onmouseover="updateImage('i18n', true);"    onfocus="updateImage('i18n',true);" onmouseout="updateImage('i18n',false);"    onblur="updateImage('i18n',false);">    <img src="greyplus.gif" border="0" alt="" id="i18n">    W3C Internationalization</a>  </body>  </html>

测试
程序
  1. 加载网页,并使用鼠标和键盘测试事件。
  2. 检查加载网页时标准图像是否按预期显示。
使用鼠标
  1. 将鼠标移动到包含事件处理程序的元素上(在本例中,它是一个锚元素)。检查图像是否变为预期的图像。
  2. 将鼠标从元素上移开。检查图像是否变回标准图像。
使用键盘
  1. 使用键盘将焦点设置到包含事件处理程序的元素。检查图像是否变为预期的图像。
  2. 使用键盘将焦点从元素上移开(通常通过将焦点移动到另一个元素上)。检查图像是否变为标准图像。
  3. 验证图像更改时页面上其他元素的布局不受影响。
预期结果

前面检查的所有步骤都是正确的。

如果这是一项足以满足成功标准的技术,测试程序的失败并不一定意味着在其他方面没有满足成功标准,而只是说明这项技术没有成功实现,不能用于声称符合标准。

SCR16:提供一个脚本,警告用户时间限制即将到期

举例

一个股票市场报价页面使用一个脚本每五分钟刷新一次页面,以确保最新的统计数据仍然可用。在五分钟时间到期前 20 秒,会出现一个确认对话框,询问用户在页面刷新前是否需要更多时间。这允许用户知道即将到来的刷新,并在需要时避免刷新。清单 A-2 创建了所描述的行为。

***清单 A-2。*使用脚本刷新页面

`

Stock Market Quotes

Stock Market Quotes

...etc...` ` `

SCR21:使用文档对象模型(DOM)的函数向页面添加内容

描述

该技术的目标是演示如何使用文档对象模型(DOM)的函数向页面添加内容,而不是使用document.writeobject.innerHTML。当使用正确的 MIME 类型(application/xhtml+xml)时,document.write()方法不支持 XHTML,并且innerHTML属性不是 DOM 规范的一部分,因此应该避免使用。

如果使用 DOM 函数添加内容,用户代理可以访问 DOM 来检索内容。createElement()函数可以用来在 DOM 中创建元素。createTextNode()用于创建与元素相关的文本。appendChild()removeChild()insertBefore()replaceChild()功能用于添加和删除元素和节点。其他 DOM 函数用于为创建的元素分配属性。

Image 注意当向文档中添加将获得焦点的元素时,不要添加tabindex属性来显式设置 tab 键顺序,因为这在向文档中间添加可聚焦元素时会导致问题。通过不显式设置一个tabindex属性,让默认的 tab 键顺序被分配给新元素。

举例

这个例子演示了使用客户端脚本来验证一个表单。如果发现错误,将显示相应的错误消息。该示例使用 DOM 函数添加错误通知,包括一个标题、一个解释错误发生的简短段落和一个有序列表中的错误列表。标题的内容被写成一个链接,这样就可以使用focus方法来引起用户对错误的注意。列表中的每一项都被编写为一个链接,当跟随该链接时,会将焦点错误地放在表单域上。

为了简单起见,这个例子只验证了两个文本字段,但是它可以很容易地扩展成一个通用的表单处理程序。客户端验证不应该是唯一的验证方式,应该与服务器端验证一起使用。客户端验证的好处是,您可以向用户提供即时反馈,使他们不必等待服务器返回错误,并且它有助于减少不必要的服务器流量。

下面是将事件处理程序添加到表单的脚本。如果启用了脚本,在表单提交给服务器之前,将调用validateNumbers()函数来执行客户端验证。如果没有启用脚本,表单将被立即提交到服务器,因此验证也应该在服务器上实现。

***清单 A-3。*向表单添加事件处理程序

`window.onload = initialise; function initialise() {   // Ensure we're working with a relatively standards compliant user agent   if (!document.getElementById || !document.createElement || !document.createTextNode)     return;

  // Add an event handler for the number form   var objForm = document.getElementById('numberform');   objForm.onsubmit= function(){return validateNumbers(this);}; }`

这是验证函数。注意使用createElement()createTextNode()appendChild() DOM 函数来创建错误消息元素。

***列举 A-4。*表单验证

function validateNumbers(objForm) {   // Test whether fields are valid   var bFirst = isNumber(document.getElementById('num1').value);   var bSecond = isNumber(document.getElementById('num2').value);   // If not valid, display errors   if (!bFirst || !bSecond)   {     var objExisting = document.getElementById('validationerrors');     var objNew = document.createElement('div');     var objTitle = document.createElement('h2');     var objParagraph = document.createElement('p');     var objList = document.createElement('ol');     var objAnchor = document.createElement('a');     var strID = 'firsterror';     var strError;     // The heading element will contain a link so that screen readers     // can use it to place focus - the destination for the link is     // the first error contained in a list     objAnchor.appendChild(document.createTextNode('Errors in Submission'));     objAnchor.setAttribute('href', '#firsterror');     objTitle.appendChild(objAnchor);     objParagraph.appendChild(document.createTextNode('Please review the following'));     objNew.setAttribute('id', 'validationerrors');     objNew.appendChild(objTitle);     objNew.appendChild(objParagraph);     // Add each error found to the list of errors     if (!bFirst)     {       strError = 'Please provide a numeric value for the first number';       objList.appendChild(addError(strError, '#num1', objForm, strID));       strID = ''; `    }     if (!bSecond)     {       strError = 'Please provide a numeric value for the second number';       objList.appendChild(addError(strError, '#num2', objForm, strID));       strID = '';     }     // Add the list to the error information     objNew.appendChild(objList);     // If there were existing errors, replace them with the new lot,     // otherwise add the new errors to the start of the form     if (objExisting)       objExisting.parentNode.replaceChild(objNew, objExisting);     else     {       var objPosition = objForm.firstChild;       objForm.insertBefore(objNew, objPosition);     }     // Place focus on the anchor in the heading to alert     // screen readers that the submission is in error     objAnchor.focus();     // Do not submit the form     objForm.submitAllowed = false;     return false;   }   return true; }

// Function to validate a number function isNumber(strValue) {   return (!isNaN(strValue) && strValue.replace(/^\s+|\s+$/, '') !== ''); }`

清单 A-5 详细说明了用于创建错误消息并将焦点设置到相关表单字段的助手函数。

***清单 A-5。*助手功能

// Function to create a list item containing a link describing the error // that points to the appropriate form field function addError(strError, strFragment, objForm, strID) {   var objAnchor = document.createElement('a');   var objListItem = document.createElement('li');   objAnchor.appendChild(document.createTextNode(strError));   objAnchor.setAttribute('href', strFragment);   objAnchor.onclick = function(event){return focusFormField(this, event, objForm);};   objAnchor.onkeypress = function(event){return focusFormField(this, event, objForm);};   // If strID has a value, this is the first error in the list   if (strID.length > 0)     objAnchor.setAttribute('id', strID); `  objListItem.appendChild(objAnchor);   return objListItem; }

// Function to place focus to the form field in error function focusFormField(objAnchor, objEvent, objForm) {   // Allow keyboard navigation over links   if (objEvent && objEvent.type == 'keypress')     if (objEvent.keyCode != 13 && objEvent.keyCode != 32)       return true;   // set focus to the form control   var strFormField = objAnchor.href.match(/[^#]\w*$/);   objForm[strFormField].focus();   return false; }`

清单 A-6 显示了示例表单的 HTML。

***清单 A-6。*样表

`

        ECMAScript Form Validation                  

Form Validation

Numeric Fields

Enter first number

Enter second number

`

这个例子仅限于客户端脚本,应该用服务器端验证来备份。该示例仅限于在客户端脚本可用时创建错误消息。

表格的工作版本可在[www.w3.org/TR/WCAG20-TECHS/working-examples/SCR21/ex1.html](http://www.w3.org/TR/WCAG20-TECHS/working-examples/SCR21/ex1.html)找到。

SCR24:根据用户请求使用渐进式增强打开新窗口

描述

这种技术的目的是避免用户没有请求的新窗口的出现所引起的混乱。突然打开新窗口会使用户迷失方向,或者被一些用户完全错过。如果文档类型不允许使用target属性(它在 HTML 4.01 Strict 或 XHTML 1.0 Strict 中不存在),或者如果开发人员不想使用它,可以用 ECMAScript 打开新窗口。下面的示例演示了如何用脚本打开新窗口:它向一个链接(a元素)添加一个事件处理程序,并警告用户内容将在一个新窗口中打开。

举例
利润

脚本包含在文档头中,链接有一个 ID,可以被脚本用作钩子,如中列出的 A-7 所示。

清单 A-7 。打开新窗口

` … Show Help</a

// Use traditional event model whilst support for event registration // amongst browsers is poor. window.onload = addHandlers;

function addHandlers() {   var objAnchor = document.getElementById('newwin');

  if (objAnchor)   {     objAnchor.firstChild.data = objAnchor.firstChild.data + ' (opens in a new window)';     objAnchor.onclick = function(event){return launchWindow(this, event);}     // UAAG requires that user agents handle events in a device-independent manner     // but only some browsers do this, so add keyboard event to be sure     objAnchor.onkeypress = function(event){return launchWindow(this, event);}   } } function launchWindow(objAnchor, objEvent) {   var iKeyCode, bSuccess=false;

  // If the event is from a keyboard, we only want to open the   // new window if the user requested the link (return or space)   if (objEvent && objEvent.type == 'keypress')   {     if (objEvent.keyCode)       iKeyCode = objEvent.keyCode;     else if (objEvent.which)       iKeyCode = objEvent.which;

    // If not carriage return or space, return true so that the user agent     // continues to process the action     if (iKeyCode != 13 && iKeyCode != 32)       return true;   }

  bSuccess = window.open(objAnchor.href);

  // If the window did not open, allow the browser to continue the default   // action of opening in the same window   if (!bSuccess)     return true;

  // The window was opened, so stop the browser processing further   return false; }`

SCR26:将动态内容插入到文档对象模型中,紧跟在其触发元素之后

描述

这种技术的目的是将插入的用户界面元素放入文档对象模型中,通过用户代理的默认行为正确设置 tab 键顺序和屏幕阅读器的阅读顺序。这种技术可以用于任何隐藏和显示的用户界面元素,比如菜单和对话框。

屏幕阅读器中的阅读顺序基于 DOM 中 HTML 或 XHTML 元素的顺序,默认的 tab 键顺序也是如此。这种技术在 DOM 中插入新内容,紧跟在被激活以触发脚本的元素之后。触发元素必须是链接或按钮,脚本必须从其onclick事件中调用。这些元素本身是可聚焦的,它们的onclick事件与设备无关。焦点保持在激活的元素上,插入到它后面的新内容成为 tab 键顺序和屏幕阅读器阅读顺序中的下一个内容。

注意,这种技术适用于同步更新。对于异步更新(有时称为 AJAX),需要一种额外的技术来通知辅助技术已经插入了异步内容。

举例

本示例在单击链接时创建一个菜单,并将其插入到链接之后。链接的onclick事件用于调用 ShowHide 脚本,将新菜单的 ID 作为参数传入,如下面的代码片段所示:

<a href="#" onclick="ShowHide('foo',this)">Toggle</a>

ShowHide 脚本创建一个包含新菜单的div,并在其中插入一个链接。最后一行是剧本的核心。它找到触发脚本的元素的父元素,并将它创建的div作为新子元素添加到该元素中。这导致新的div出现在链接之后的 DOM 中。当用户按下 Tab 键时,焦点将转到菜单中第一个可聚焦的项目,也就是我们创建的链接。(参见清单 A-8 。)

***清单 A-8。*使用 ShowHide

function ShowHide(id,src) {         var el = document.getElementById(id);         if (!el)         {                 el = document.createElement("div");                 el.id = id;                 var link = document.createElement("a");                 link.href = "javascript:void(0)";                 link.appendChild(document.createTextNode("Content"));                 el.appendChild(link);                 src.parentElement.appendChild(el);         }         else         {                 el.style.display = ('none' == el.style.display ? 'block' : 'none');         } }

级联样式表用于使div和链接看起来像一个菜单。

测试:程序
  1. 查找页面中触发非弹出窗口对话框的所有区域。
  2. 检查对话框是否由按钮或链接的 click 事件触发。
  3. 使用允许您检查脚本生成的 DOM 的工具,检查对话框是否在 DOM 中的下一个位置。
预期结果

#2 和#3 是正确的。

如果这对于成功标准来说是一项充分的技术,那么测试程序的失败并不一定意味着在其他方面没有满足成功标准,而仅仅意味着这项技术没有被成功地实现,不能用于声称符合性。

SCR28:使用可展开和可折叠的菜单绕过内容块

描述

这种技术允许用户跳过重复的材料,方法是将材料放在一个菜单中,该菜单可以在用户控制下展开或折叠。用户可以通过折叠菜单跳过重复的材料。用户调用用户界面控件来隐藏或移除菜单的元素。

Image 类似的方法可以通过使用服务器端脚本和重新加载网页的修改版本来实现。

例 1

网页顶部的导航链接都是使用 HTML、CSS 和 JavaScript 实现的菜单中的条目。当导航栏展开时,导航链接可供用户使用。当导航栏折叠时,链接不可用。清单 A-9 中的代码详细说明了这一功能。

***清单 A-9。*可扩展菜单

`  

...

  Toggle Navigation Bar

  

`

此代码的一个工作示例可在[www.w3.org/TR/WCAG20-TECHS/working-examples/SCR28/toggle-navbar.html](http://www.w3.org/TR/WCAG20-TECHS/working-examples/SCR28/toggle-navbar.html)获得。

例 2

一组网页的目录在每个网页的开头附近重复出现。目录开头的按钮允许用户在页面上删除或恢复目录。

***列举 A-10。*目录

`   

  ...

  Toggle Table of Contents   

    ...   
`

这里可以找到这个代码的一个工作示例:[www.w3.org/TR/WCAG20-TECHS/working-examples/SCR28/toggle-toc.html](http://www.w3.org/TR/WCAG20-TECHS/working-examples/SCR28/toggle-toc.html)

SCR32:提供客户端验证并通过 DOM 添加错误文本

描述

这种技术的目的是演示当表单域的客户端验证失败时错误消息的显示。锚元素用于在列表中显示错误消息,并被插入到要验证的字段上方。在错误消息中使用锚元素,以便将焦点放在错误消息上,引起用户的注意。锚元素的href包含一个页面内链接,该链接引用了发现错误的字段。

在已部署的应用中,如果关闭 JavaScript,客户端验证将不会发生。因此,只有在依赖脚本来实现一致性的情况下,或者在使用服务器端验证技术来捕捉任何错误并返回包含错误字段信息的页面时,这种技术才足够。

举例

此示例验证必填字段以及需要特定格式的字段。当识别出一个错误时,脚本将一个错误消息列表插入到 DOM 中,并将焦点移到它们上面,如图图 A-1 所示。

Image

***图 A-1。*可访问的验证样本表格

HTML 和 JavaScript 代码

示例表单的 HTML 出现在清单 A-11 的中。

***清单 A-11。*用于客户端验证的 HTML】

`

             Form Validation                           

        

The following form is validated before being submitted if scripting is available,             otherwise the form is validated on the server. All fields are required, except Imagethose marked optional. If errors are found in the submission, the form is cancelled and a list of errors is displayed at the top of the form.

        

Please enter your details below.

        

Validating Form

        

            
                             Personal Details                 

                    Please enter your forename                     <input type="text" size="20" name="forename" id="forename" class="string"                         value=""/>                 

                

                    Please enter your age                                      

                

                    Please enter your email address                     <input type="text" size="20" name="email" id="email" class="email"Image  value=""/>                 

                         

                             

                 

Second Form

                     
                             Second Form Details                 

                    Enter a suggestion                     <input type="text" size="20" name="suggestion" id="suggestion"                       class="string" value=""/>                 

                

                    Please enter your email address (optional)                     <input type="text" size="20" name="optemail" id="optemail"                         class="optional email" value=""/>                 

                

                    Please rate this suggestion                     <input type="text" size="20" name="rating" id="rating"                       class="number" value=""/>                 

                

                    Enter some jibberish (optional)                                      

            

            

                             

             

`

清单 A-12 中的详细描述了执行验证和插入错误消息的 JavaScript。

***清单 A-12。*验证 JavaScript

`window.onload = initialise;

function initialise() {    var objForms = document.getElementsByTagName('form');    var iCounter;

   // Attach an event handler for each form    for (iCounter=0; iCounter<objForms.length; iCounter++)    {       objForms[iCounter].onsubmit = function(){return validateForm(this);};    } }

// Event handler for the form function validateForm(objForm) {    var arClass = [];    var iErrors = 0; var objField = objForm.getElementsByTagName('input');    var objLabel = objForm.getElementsByTagName('label');    var objList = document.createElement('ol');    var objError, objExisting, objNew, objTitle, objParagraph, objAnchor, objPosition;    var strLinkID, iFieldCounter, iClassCounter, iCounter;

   // Get the id or name of the form, to make a unique    // fragment identifier    if (objForm.id)    {       strLinkID = objForm.id + 'ErrorID';    }    else    {       strLinkID = objForm.name + 'ErrorID';    }

   // Iterate through input form controls, looking for validation classes    for (iFieldCounter=0; iFieldCounter<objField.length; iFieldCounter++)    {       // Get the class for the field, and look for the appropriate class       arClass = objField[iFieldCounter].className.split(' ');       for (iClassCounter=0; iClassCounter<arClass.length; iClassCounter++)       {          switch (arClass[iClassCounter])          {             case 'string':                if (!isString(objField[iFieldCounter].value, arClass))                {                   if (iErrors === 0)                   {                      logError(objField[iFieldCounter], objLabel, objList, strLinkID);                   }                   else                   {                      logError(objField[iFieldCounter], objLabel, objList, '');                   }                   iErrors++; }                break;             case 'number':                if (!isNumber(objField[iFieldCounter].value, arClass))                {                   if (iErrors === 0)                   {                      logError(objField[iFieldCounter], objLabel, objList, strLinkID);                   }                   else                   {                      logError(objField[iFieldCounter], objLabel, objList, '');                   }                   iErrors++;                }                break;

            case 'email' :                if (!isEmail(objField[iFieldCounter].value, arClass))                {                   if (iErrors === 0)                   {                      logError(objField[iFieldCounter], objLabel, objList, strLinkID);                   }                   else                   {                      logError(objField[iFieldCounter], objLabel, objList, '');                   }                   iErrors++;                }                break;          }       }    }

   if (iErrors > 0)    {       // If not valid, display error messages       objError = objForm.getElementsByTagName('div');

      // Look for existing errors       for (iCounter=0; iCounter<objError.length; iCounter++)       {          if (objError[iCounter].className == 'validationerrors')          {             objExisting = objError[iCounter];          }       }

      objNew = document.createElement('div');       objTitle = document.createElement('h2');       objParagraph = document.createElement('p');       objAnchor = document.createElement('a');

      if (iErrors == 1)       {          objAnchor.appendChild(document.createTextNode('1 Error in Submission'));       }       else       {          objAnchor.appendChild(document.createTextNode(iErrors + ' Errors in Submission'));       }       objAnchor.href = '#' + strLinkID;       objAnchor.className = 'submissionerror';

      objTitle.appendChild(objAnchor); objParagraph.appendChild(document.createTextNode('Please review the following'));       objNew.className = 'validationerrors';

      objNew.appendChild(objTitle);       objNew.appendChild(objParagraph);       objNew.appendChild(objList);

      // If there were existing errors, replace them with the new lot,       // otherwise add the new errors to the start of the form       if (objExisting)       {          objExisting.parentNode.replaceChild(objNew, objExisting);       }       else       {          objPosition = objForm.firstChild;          objForm.insertBefore(objNew, objPosition);       }

      // Allow for latency       setTimeout(function() { objAnchor.focus(); }, 50);

      // Don't submit the form       objForm.submitAllowed = false;       return false;    }

   // Submit the form    return true; }

// Function to add a link in a list item that points to problematic field control function addError(objList, strError, strID, strErrorID) {    var objListItem = document.createElement('li');    var objAnchor = document.createElement('a');

   // Fragment identifier to the form control    objAnchor.href='#' + strID;

   // Make this the target for the error heading    if (strErrorID.length > 0)    {       objAnchor.id = strErrorID;    }

   // Use the label prompt for the error message    objAnchor.appendChild(document.createTextNode(strError));    // Add keyboard and mouse events to set focus to the form control    objAnchor.onclick = function(event){return focusFormField(this, event);};    objAnchor.onkeypress = function(event){return focusFormField(this, event);};    objListItem.appendChild(objAnchor); objList.appendChild(objListItem); }

function focusFormField(objAnchor, objEvent) {    var strFormField, objForm;

   // Allow keyboard navigation over links    if (objEvent && objEvent.type == 'keypress')    {       if (objEvent.keyCode != 13 && objEvent.keyCode != 32)       {          return true;       }    }

   // set focus to the form control    strFormField = objAnchor.href.match(/[^#]\w*$/);    objForm = getForm(strFormField);    objForm[strFormField].focus();    return false; }

// Function to return the form element from a given form field name function getForm(strField) {    var objElement = document.getElementById(strField);

   // Find the appropriate form    do    {       objElement = objElement.parentNode;    } while (!objElement.tagName.match(/form/i) && objElement.parentNode);

   return objElement; }

// Function to log the error in a list function logError(objField, objLabel, objList, strErrorID) {    var iCounter, strError;

   // Search the label for the error prompt    for (iCounter=0; iCounter<objLabel.length; iCounter++)    {       if (objLabel[iCounter].htmlFor == objField.id)       {          strError = objLabel[iCounter].firstChild.nodeValue;       }    }

   addError(objList, strError, objField.id, strErrorID); }

// Validation routines - add as required

function isString(strValue, arClass) {    var bValid = (typeof strValue == 'string' && strValue.replace(/^\s*|\s*$/g, '')      !== '' && isNaN(strValue));

   return checkOptional(bValid, strValue, arClass); }

function isEmail(strValue, arClass) {    var objRE = /^[\w-.']{1,}@([\da-zA-Z-]{1,}.){1,}[\da-zA-Z-]{2,}$/;    var bValid = objRE.test(strValue);

   return checkOptional(bValid, strValue, arClass); }

function isNumber(strValue, arClass) {    var bValid = (!isNaN(strValue) && strValue.replace(/^\s*|\s*$/g, '') !== '');

   return checkOptional(bValid, strValue, arClass); }

function checkOptional(bValid, strValue, arClass) {    var bOptional = false;    var iCounter;

   // Check if optional    for (iCounter=0; iCounter<arClass.length; iCounter++)    {       if (arClass[iCounter] == 'optional')       {          bOptional = true;       }    }

   if (bOptional && strValue.replace(/^\s*|\s*$/g, '') === '')    {       return true;    }

   return bValid;    }`

使用 PHP、JavaScript、CSS 和 XHTML 实现这种技术的一个工作示例可以在这里找到:[www.w3.org/TR/WCAG20-TECHS/working-examples/SCR32/index.php](http://www.w3.org/TR/WCAG20-TECHS/working-examples/SCR32/index.php)

SCR35:使用锚和按钮的 onclick 事件使操作键盘可访问

描述

这项技术的目的是演示如何通过将脚本函数附加到键盘可访问的控件上,以键盘可访问的方式调用脚本函数。为了确保可以从键盘调用脚本动作,它们与本地可操作的 HTML 元素(链接和按钮)相关联。这些元素的onclick事件与设备无关。虽然“onclick”听起来像是和鼠标捆绑在一起,但onclick事件实际上是映射到一个链接或按钮的默认动作。当用户用鼠标单击元素时,会发生默认操作,但当用户聚焦元素并按 Enter 或空格键时,以及当元素通过可访问性 API 被触发时,也会发生默认操作。

这种技术依赖于客户端脚本。然而,为脚本不可用的环境提供备份实现或解释是有益的。当使用锚元素调用 JavaScript 动作时,通过href属性提供备份实现或解释。使用按钮时,它是通过表单帖子提供的。

例 1

清单 A-13 中的代码创建了一个运行脚本的链接,但是当脚本不可用时,它会导航到另一个页面。当且仅当导航目标提供与脚本相同的功能时,这种方法可以用来创建不依赖于脚本的站点。这个例子与上一节中的例子相同,除了它的href现在被设置为一个真实的页面,dostuff.htm.``dostuff.htm页面必须提供与脚本相同的功能。return false;”在doStuff()事件结束时,处理函数告诉浏览器不要导航到 URI。没有它,浏览器会在脚本运行后导航到dostuff.htm

***清单 A-13。*创建运行脚本的链接

<script> function doStuff()  {   //do stuff     return false;  } </script> <a href="dostuff.htm" onclick="return doStuff();">do stuff</a>

此代码的一个工作示例可在[www.w3.org/TR/WCAG20-TECHS/working-examples/SCR35/jslink.html](http://www.w3.org/TR/WCAG20-TECHS/working-examples/SCR35/jslink.html)获得。

例 2

清单 A-14 为没有脚本的用户创建一个运行脚本并返回表单帖子的按钮。当且仅当表单帖子提供与脚本相同的功能时,不依赖脚本的站点才可以使用这种方法。onsubmit="return false;"阻止表单提交。

***清单 A-14。*创建一个按钮来运行一个脚本,表单发布作为后备

`

  `

下面是这段代码的一个工作示例:[www.w3.org/TR/WCAG20-TECHS/working-examples/SCR35/jsbutton.html](http://www.w3.org/TR/WCAG20-TECHS/working-examples/SCR35/jsbutton.html)

SCR37:以独立于设备的方式创建定制的 aialogs

描述

站点设计者通常希望创建不使用浏览器提供的弹出窗口的对话框。这通常是通过将对话框内容放在一个div中,并使用 CSS 中的 z 顺序和绝对定位将div放置在页面内容上方来实现的。

为了便于访问,这些对话框必须遵循一些简单的规则。

  • 从链接或按钮的onclick事件触发启动对话框的脚本。
  • 将对话框div放在文档对象模型(DOM)中触发它的元素之后。触发元素将保持焦点,在该元素之后插入对话框内容将使对话框中的内容成为屏幕阅读器阅读顺序和 tab 键顺序的下一个。在视觉上,对话框仍然可以完全定位在页面上的其他位置。这可以通过在 HTML 中创建对话框并用 CSS 隐藏它来实现,如下例所示,也可以通过用脚本将它直接插入到触发元素之后来实现。
  • 确保对话框div中的 HTML 与其他内容一样满足相同的可访问性标准。
  • 让启动链接切换对话框的打开和关闭,并在键盘焦点离开时关闭对话框,这也很好,但并不总是必要的。
举例

这个例子的 HTML 包括一个触发元素——在这个例子中是一个按钮——和一个作为对话框框架的div

触发元素是一个按钮,脚本从onclick事件触发。这将向操作系统发送适当的事件,以便辅助技术知道 DOM 中的变化。

在这个例子中,对话框中的提交和重置按钮只是隐藏了div

***清单 A-15。*打开对话框的选项按钮

`... <button onclick="TogglePopup(event,true)"         name="pop0001">Options

  

Edit Sort Information

              Sort Order       Alphabetical       Default     
     
...`

divheadingform元素用 CSS 样式化,看起来像一个对话框,如清单 A-16 中的所示。

***清单 A-16。*造型形式元素

`... a { color:blue; } a.clickPopup img { border:none; width:0; }

div.popover { position:absolute; display:none; border:1px outset; background-color:beige;Image  font-size:80%; background-color:#eeeeee; color:black; } div.popover h3 { margin:0; padding:0.1em 0.5em; background-color:navy; color:white; } #pop0001 { width:20em; } #pop0001 form { margin:0; padding:0.5em; } #pop0001 fieldset { margin-bottom:0.3em; padding-bottom:0.5em; } #pop0001 input, #pop0001 label { vertical-align:middle; } #pop0001 div.buttons { text-align:right; } #pop0001 div.buttons input { width:6em; } ...`

该脚本切换弹出窗口div的显示,显示和隐藏。参见清单 A-17 。

***清单 A-17。*显示弹出窗口

... function TogglePopup(evt,show) `{         HarmonizeEvent(evt);         var src = evt.target;         if ("click" == evt.type)         {                 evt.returnValue = false;         }         var popID = src.getAttribute("name");         if (popID)         {                 var popup = document.getElementById(popID);                 if (popup)                 {                         if (true == show)                         {                                 popup.style.display = "block";                         }                         else if (false == show)                         {                                 popup.style.display = "none";                         }                         else                         {                                 popup.style.display = "block" == popup.style.display ?Image  "none" : "block";                         }                         if ("block" == popup.style.display)                         {                                 //window.alert(document.documentElement.scrollHeight);                                 popup.style.top = ((document.documentElement.offsetHeight –Image  popup.offsetHeight) / 2 ) + 'px';                                 popup.style.left = ((document.documentElement.offsetWidth –Image  popup.offsetWidth) / 2) + 'px';                         }                 }         } }

function SubmitForm(elem) {         elem.parentNode.style.display='none';         return false; }

function ResetForm(elem) {         elem.parentNode.style.display='none';         return false; } ...`

这里有一个工作示例:[www.w3.org/TR/WCAG20-TECHS/working-examples/SCR37/default.htm](http://www.w3.org/TR/WCAG20-TECHS/working-examples/SCR37/default.htm),它是一个打开对话框的选项按钮。

如前所述,这里提供了完整的技术列表:[www.w3.org/TR/WCAG20-TECHS/client-side-script.html](http://www.w3.org/TR/WCAG20-TECHS/client-side-script.html)