本页内容
简介 | |
生成 XHTML Web 站点 | |
XHTML 标准的版本 | |
创建 XHTML 页 | |
XHTML 和 ASP.NET 控件 | |
验证 XHTML 页 | |
XHTML 和 DOCTYPE 切换 | |
MIME 类型" hspace=4 src="http://uml.org.cn/net/images/down.gif" width=7 vspace=2 border=0> | XHTML 和 MIME 类型 |
配置 XHTML 一致性 | |
生成可访问的 ASP.NET Web 站点 | |
可访问性标准 | |
ASP.NET 2.0 中的可访问性改进 | |
创建可访问的图像 | |
创建可访问的表单 | |
创建可访问的导航 | |
创建可访问的数据 | |
创建可访问的 XHTML | |
创建可访问的脚本 | |
验证页的可访问性 | |
示例应用程序:可访问的 XHTML ASP.NET Web 站点 | |
访问 Amazon Web 服务 | |
默认页 | |
默认页的 XHTML 功能 | |
默认页的可访问性功能 | |
搜索页 | |
搜索页的 XHTML 功能 | |
搜索页的可访问性功能 | |
母版页 | |
母版页的 XHTML 功能 | |
母版页的可访问性功能 | |
小结 |
简介
Web 标准使您能通过最少的工作,生成可被最广大受众访问的 Web 站点。Web 标准的承诺是:只需设计页面一次,即可让该页以完全相同的方式在任何现代的浏览器中显示和工作。例如,在按照标准生成以后,旨在在 Microsoft Internet Explorer 中以某种方式显示的页可在其他浏览器(如,Mozilla Firefox、Netscape Navigator、Opera、Camino 和 Safari)中以相同的方式显示,而无需完成任何额外的工作。
Web 标准的一个额外好处是 — 使 Web 站点更易于为残疾人士访问。这是一个范围广泛的受众群体,包括视力衰退的中年人士,刚刚在滑雪时跌断胳膊的人士,以及完全失明的人士等。使用标准可避免无意中阻止那些具有暂时性或永久性身体残疾的人士访问 Web 页。
对于生成满足公共 Web 标准的 Web 站点而言,Microsoft ASP.NET 2.0 框架是最佳的框架。特别强调的是,ASP.NET 2.0 框架中的每个控件都按照 XHTML 和可访问性标准进行了全面的检查和测试。此外,Microsoft Visual Studio .NET 2005 还包含一些新工具,用于按照 XHTML 和可访问性标准验证 Web 页。
本文的目的是为您提供有关 XHTML 和可访问性标准的概述,并说明如何利用 ASP.NET 2.0 和 Visual Studio .NET 2005 来满足这些标准。在本文的结尾,将分步演练以下功能,即创建能够同时满足 XHTML 和可访问性标准的 ASP.NET 2.0 Web 站点。
生成 XHTML Web 站点
HTML 在正式的场合已经过时了。World Wide Web Consortium (W3C) 于 2000 年 6 月 26 日发布了 XHTML 的第一个版本作为推荐标准。XHTML 标准的目标是取代 HTML。按照 W3C 的说法,“XHTML 是 HTML 的继承者”(http://www.w3.org/MarkUp/)。
XHTML 标准的制定者具有两大目标:
• |
在文档结构和表示形式之间创建更明显的分离。 |
• |
将 HTML 重新表示为 XML 的应用程序。 |
为了实现第一个目标,W3C 一直在坚定地从 HTML 中删除纯粹描述性的元素和属性(他们是从 HTML 4.0 开始这一过程的)。例如,XHTML 1.0 Strict 不包含诸如 <font> 标记之类的元素或诸如 bgcolor 属性之类的属性,因为这些元素和属性完全用于描述文档的外观,它们与文档的结构没有任何关系。
W3C 一直在努力使 Web 站点设计人员和开发人员摒弃特定标记应当具有特定外观这一观念。例如,您可能会认为 <h1> 标记(标题标记)的用途是在页中呈现大的加粗文本。这实际上是错的。<h1> 标记用来在文档中标记标题而不是其他任何东西。如何呈现标题标记由浏览器确定。视力衰退的人士使用的屏幕阅读器可能利用抑扬顿挫的声音来大声朗读标题标记的内容。不支持多个字体大小的 PDA 可能用闪烁文本呈现标题标记的内容。
您不应当试图使用诸如 <h1> 标记之类的页元素来控制 Web 页的外观。相反,您应当通过使用层叠样式表来指示 Web 页的外观。而且,您所使用的层叠样式表应当是外部 层叠样式表。请使用标记和属性来标记文档的结构,而使用样式表来控制文档的表示形式。
XHTML 的第二个目标是迫使 HTML 开发人员遵守更为严格的 XML 规则。按照 W3C 的说法,“XHTML 1.0 是 HTML 4.01 的作为 XML 1.0 应用程序的修订”(http://www.w3.org/MarkUp/)。换句话说,使用 XHTML 生成 Web 页时,实际上是在创建 XML 文档。
XML 文档具有比 HTML 文档更严格的语法。例如,XML 区分大小写,所有 XML 属性都必须放在引号内,而且 XML 标记不能重叠。强迫 Web 站点开发人员和设计人员遵守有更高要求的语言规则有很多好处。
好处之一,用 XHTML 标记编写的页具有更高的跨浏览器、跨设备和跨操作系统兼容性。如果在浏览器中打开传统的 HTML 页,浏览器将千方百计地呈现该页。浏览器将试图呈现该页,即使您的 HTML 一团糟。例如,Internet Explorer(以及 Firefox 和 Opera)能够很好地显示下面的 HTML 页。
<i><B>this is bold and italic</I> and this is bold </body></HTML>
Internet Explorer 会恰当地显示该页 — 即使该页缺少 <html> 和 <body> 开始标记,<b> 标记不具有匹配的结束标记,并且开始和结束 <i> 标记的大小写不一致。所有主要的浏览器都能适应几乎任何 HTML 标记“混合物”,并且不顾一切地呈现一些内容。
浏览器的这种适应行为是危险的,因为不同的浏览器(或相同浏览器的将来版本,或在不同操作系统上运行的相同浏览器)可能以不同方式呈现错乱的 HTML。实际上,对于最新版本的 Internet Explorer、Mozilla Firefox 和 Opera 而言,它们呈现无效 HTML 的方式惊人地一致。但是,一旦开始违反游戏规则,就不会得到任何保证。
然而,如果用 XHTML 的更严格的规则编写 Web 页,那么 Web 页就更有可能以一致的方式与当前浏览器协作,并且它们将继续与当前浏览器的未来新版本协作。对于任何公司而言,几乎都不具备针对每个浏览器、在每个操作系统和每个设备上测试其 Web 站点的资源。如果按照 Web 标准编写页面,那么就不必具有这样的资源。
XHTML 标准的版本
有三个版本的 XHTML 1.0,它们分别对应三个版本的 HTML 4.01:
• |
XHTML 1.0 Transitional |
• |
XHTML 1.0 Strict |
• |
XHTML 1.0 Frameset |
XHTML 1.0 Transitional 包含 HTML 4.01 Transitional 中的全部标记和属性。引入 XHTML 1.0 Transitional 标准的目的是,使现有 HTML 设计人员和开发人员无需经历太多的痛苦就能迁移到 XHTML。
XHTML 1.0 Strict 与 XHTML 1.0 Transitional 的不同之处在于,它在文档结构和表示形式之间实施了一种更为明显的分离。与 XHTML 1.0 Transitional 不同,XHTML 1.0 Strict 强迫您使用层叠样式表来控制页的外观。
XHTML 1.0 Frameset 文档意在成为使用 <frameset> 标记将浏览器划分为多个框架的文档(XHTML 1.0 Transitional 和 Strict 页不能包含 <frameset> 标记)。
W3C 还发布了 XHTML 1.1 以作为推荐标准(2001 年 5 月 31 日)。XHTML 1.1 非常类似于 XHTML 1.0 Strict。二者的主要区别在于,可以用附加模块扩展 XHTML 1.1 以便支持新元素。例如,可以生成特定的 XHTML 1.1 页,该页还包含 MathML(数学标记语言)、SVG(可伸缩向量语言)或创建的自定义模块中的元素。
最后,W3C 正在制订 XHTML 2.0 推荐标准。因为 XHTML 2.0 仍然处于起草阶段,并且当前没有 Web 浏览器支持该标准,所以我们不在本文讨论它。
ASP.NET 2.0 框架和 Visual Studio .NET 2005 面向 XHTML 1.0 Transitional。该标准是 XHTML 标准中限制性最低的,而且它是与现有 HTML 页最兼容的标准。但是,还可以生成面向 XHTML 1.0 Strict 标准甚至 XHTML 1.1 标准的 ASP.NET 2.0 页(请参阅后面的“配置 XHTML 一致性”一节)。
(请注意,默认情况下,ASP.NET 框架的 Beta 2 版本面向 XHTML 1.1。 ASP.NET 2.0 框架的最终版本将面向 XHTML 1.0 Transitional。)
创建 XHTML 页
与 HTML 页不同,XHTML 页必须是标准格式且有效的 XML 文档。XHTML 1.0 推荐标准的第 4 部分对 HTML 和 XHTML 之间的区别进行了总结。这里给出生成有效 XHTML 页的最重要需求的列表:
• |
页必须包含有效的 XHTML DOCTYPE。 有效的 XHTML 页必须在其任何内容之前包含一个 XHTML DOCTYPE。当在 Visual Studio .NET 2005 或 Microsoft Visual Web Developer 中创建新的 ASP.NET 页时,该页中将自动包含 XHTML 1.0 Transitional 的正确的 DOCTYPE。下面列出四个标准的 XHTML DOCTYPE: XHTML 1.0 Transitional <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> XHTML 1.0 Strict <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> XHTML 1.0 Frameset <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> XHTML 1.1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 向页中添加 DOCTYPE 会影响该页在浏览器中的呈现方式。请参阅以下标题为“XHTML 和 DOCTYPE 切换”的一节。 |
• |
根元素必须引用 XHTML 命名空间。 XHTML 页的开始 <html> 标记必须指定默认命名空间 http://www.w3.org/1999/xhtml。以下是 XHTML 1.0 Transitional 页的有效开始 <html> 标记的示例: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
• |
所有元素和属性名都必须小写。 XML 区分大小写。因此,在 <p> 标记和 <P> 标记之间存在差异。只有前者是有效的 XHTML 段落标记。 |
• |
属性值必须始终放在引号内。 确保始终将属性值放在双引号或单引号中。例如,以下是无效的 XHTML。 <a href=SomePage.aspx>Next</a> 在该示例中,href 属性缺少引号。以下代码是有效的 XHTML。 <a href=SomePage.aspx>Next</a> 您可以通过选择菜单选项 Tools、Options、Format,将 Visual Studio .NET 2005 和 Visual Web Developer 配置为自动将属性值放在引号内。 |
• |
所有具有开始标记的非空元素都必须具有匹配的结束标记。 如果具有开始 <p> 标记,则必须包含结束 </p> 标记来标记段落的结束。对于根本不包含任何内容的标记,例如 <br> 标记,可同时提供开始和结束标记 <br></br>,也可以使用空元素简写 为使 XHTML 页与现有的 HTML 浏览器向后兼容,需要小心处理打开和关闭标记的方式。例如,现有 HTML 浏览器倾向于将开始和结束 <br> </br> 标记错误地解释为两个 <br> 元素。因此,您应当使用空元素简写</br>。 此外,除非您小心地在结束斜杠之前添加一个空格,否则现有 HTML 浏览器在处理空元素简写时会出现问题。因此,应当使用 <BR< b>[space] />(而不是)向页中添加 <br> 元素。 |
• |
不得存在重叠标记。 可以使标记嵌套,但是不允许使标记重叠。例如,以下 XHTML 是有效的。 <b><i>This is bold and italic</i></b> 但是,以下 XHTML 是无效的。 <i><b>This is bold and italic</i></b> |
• |
不得存在属性最简化。 所有属性都必须具有值,即使该值看起来有一点儿奇怪。例如,标记<input type="checkbox" checked />是无效的 XHTML,因为 checked 属性不具有值。该标记应当写成<input type="checkbox" checked />。 |
• |
必须使用 id 属性而不是 name 属性。 在 HTML 中,可以使用 name 属性来标识 <a>、<applet>、<form>、<frame>、<iframe>、<img> 和 <map> 元素。尽管可以使用 name 属性生成 XHTML 1.0 Transitional 页,但在 XHTML 1.0 Strict 和 XHTML 1.1 标准中已经将 name 属性删除。您应当改而使用 id 属性来标识这些元素。 |
• |
必须将 <script> 和 <style> 元素的内容包装到 CDATA 节中。 如果在脚本或样式表中使用特殊字符(例如 < 或 &)或实体引用(例如 < 或 &),则需要将脚本或样式表的内容标记为 CDATA(字符数据)节,如下所示。 <script type="text/javascript"> <![CDATA[ function isLess(a, b) { if (a < b) return true; } ]]> </script> 使用 CDATA 节并非对所有浏览器都有效。例如,Internet Explorer 会将 <script> 标记中的 CDATA 节视为语法错误。可以通过添加 JavaScript 注释避免该问题,如下所示。 <script type="text/javascript"> /* <![CDATA[ */ function isLess(a, b) { if (a < b) return true; } /* ]]> */ </script> JavaScript 使用 /* 和 */ 来标志注释的开始和结束。因此,CDATA 节对 JavaScript 隐藏,但不对分析该页的浏览器隐藏。总之,较好的做法是将样式规则和脚本放在外部文件中,而从 XHTML 页中引用这些文件。通过使用外部样式表和脚本,能够避免上述所有问题。 |
XHTML 和 ASP.NET 控件
默认情况下,ASP.NET 2.0 框架中包含的每个 ASP.NET 控件都呈现有效的 XHTML。换句话说,向页中添加 ASP.NET 控件时,您无需完成任何特殊工作来生成有效的 XHTML 标记。例如,如果您向页中添加 GridView 控件,则 GridView 控件会生成有效的 XHTML 标记。
这里需要澄清三个要点。首先,包含 ASP.NET 控件的页的源代码不会通过 XHTML 验证。验证 ASP.NET 页时,需要验证页呈现的内容(在 Internet Explorer 中选择 View Source 时看到的所有内容),而不是该页的源代码。
其次,在创建 ASP.NET 页时,没有任何事情阻止您编写无效的 XHTML。您当然可以向 ASP.NET 页中添加希望添加的任何标记。例如,如果向页中添加 标记,那么页将不会通过 XHTML 1.0 Strict 验证。
最后,当您使用自定义 ASP.NET 控件时,没有任何保证。如果购买第三方 ASP.NET 控件(例如,一个一流的增强 DataGrid 控件),则该控件可能会呈现有效的 XHTML,但也可能不会。保证不犯错误是控件供应商的责任。
验证 XHTML 页
Visual Studio .NET 2005 和 Visual Web Developer 会在生成 Web 页的过程中自动验证该页的有效性。通过在违反规则的内容下添加绿色或红色波浪线,在“Source”视图中指出验证问题。红色波浪线对应于诸如缺少结束标记之类的验证错误。绿色波浪线对应于验证警告,例如,使用了已否决的标记。
将鼠标悬停在任何波浪线上方,可查看包含验证错误或警告消息的工具提示(参见图 1)。或者,还可以在 Error List 窗口中查看验证错误或警告的列表(依次选择 View、Other Windows、Error List)。
图 1. 验证 XHTML 文档
默认情况下,Visual Studio .NET 2005 和 Visual Web Developer 被配置为针对 Internet Explorer 6.0 架构验证页。如果要针对 XHTML 架构验证页,则需要从工具栏的下拉列表中选择 XHTML 架构中的一个,或依次选择 Tools、Options、Validation 来选择目标架构。
作为替代方法,还可以通过使用 W3C验证服务来验证 ASP.NET 页。W3C 验证服务使您能够通过提供 URL 或通过上载 XHTML 页的源代码来验证页。
XHTML 和 DOCTYPE 切换
为 Web页指定 DOCTYPE 会影响浏览器呈现页的方式。Internet Explorer、Mozilla Firefox 和 Opera 全都支持一种名为“DOCTYPE 切换”(也叫“DOCTYPE 嗅探”)的功能。
引入 DOCTYPE 切换的目的是使浏览器能够正确地呈现符合标准的 Web 站点以及旧式 Web 站点。大多数 Web 站点被开发为呈现 HTML 页而不是 XHTML 页。浏览器通过判断是否存在 DOCTYPE 来确定何时应该使用标准来呈现页。
Internet Explorer 6+ 支持两种呈现模式,分别叫做 Quirks 模式和 Standards 模式。当 Internet Explorer 呈现包含有效 XHTML(或 HTML 4.0)DOCTYPE 的页时,它会以 Standards 模式呈现该页;否则,它会以 Quirks模式呈现该页(有关详细信息,请参阅 CSS Enhancements in Internet Explorer 6)。
Opera 浏览器 (Opera 7+) 支持与 Internet Explorer 相同的两种呈现模式:Quirks 和 Standards(有关详细信息,请参阅 http://www.opera.com/docs/specs/doctype/)。
Mozilla Firefox 1+ 支持三种呈现模式:Quirks 模式、Almost Standards 模式和 Standards 模式。Firefox 的 Almost Standards 模式对应于 Internet Explorer 和 Opera 的 Standards 模式。当页包含有效的 XHTML 1.0 Transitional DOCTYPE(并且该页被分配为 text/html MIME 类型)时,Firefox 会以 Almost Standards 模式呈现该页。当页包含 XHTML 1.0 Strict 或 XHTML 1.1 DOCTYPE(或者该页被分配为 XML MIME 类型)时,该页将以 Standards 模式呈现(有关详细信息,请参阅 http://www.mozilla.org/docs/web-developer/quirks/doctypes.html)。
可以通过临时向页中添加以下客户端脚本(该脚本在最新版本的 Internet Explorer、Firefox 和 Opera 中有效)确定浏览器的当前呈现模式。
<script type="text/javascript"> alert( document.compatMode ); </script>
您需要关心浏览器的呈现模式,因为它会影响将层叠样式表应用于该页的方式。如果将现有 HTML 页转换为 XHTML 页,那么在浏览器中打开它们时,它们可能看起来非常不同。
例如,Internet Explorer 以不同方式计算页元素的大小,这取决于呈现模式(它使用不同的 CSS Box Model)。在 Quirks 模式下,元素的宽度是通过将元素的内容、内边距、边框和边距相加而计算得到的。在 Standards 模式下,元素的宽度是只考虑元素内容的宽度而计算得到的。
例如,考虑下列两个 <div> 标记。
<div style="width:400px;border:solid 1px black"> First Box </div> <div style="width:400px;border:solid 1px black;padding:10px"> Second Box </div>
除了第二个 <div> 元素的附加内边距以外,这两个 <div> 元素是相同的。在 Quirks 模式(参见图 2)下,这两个 <div> 元素看起来大小相同,因为在计算第二个 <div> 元素的宽度时考虑了它的附加内边距(这两个元素的总宽度为 400px)。在 Standards 模式(参见图 3)下,第二个 <div> 元素看起来要比第一个 <div> 元素宽,因为在计算元素的宽度时未考虑内边距(这两个元素的总宽度大于 400px)。
图 2. Quirks 模式
图 3. Standards 模式
这只是 Quirks 模式下浏览器差异的一个示例。在 Quirks 模式下,每个浏览器都以相当不同的方式实现 W3C层叠样式表标准。有关切换到 Standards 模式的一个妙处在于,它强制几乎所有现代浏览器以非常类似的方式(不完全相同,但要好得多)解释 W3C标准。
如果希望 Web 页以相同方式出现在所有浏览器中,那么通过包含 XHTML 1.0 Transitional DOCTYPE 触发 Standards 模式(在 Internet Explorer 和 Opera 中)和 Almost Standards 模式(在 Firefox 中)是一个好主意。幸运的是,默认情况下,Visual Studio .NET 2005 和 Visual Web Developer 自动将该 DOCTYPE 添加到每个新的 ASP.NET 页中。
XHTML 和 MIME 类型
当 Web 浏览器从 Web 服务器请求页时,Web 服务器会为该页分配特定的 MIME 类型(也称为 Content 类型)。例如,HTML 页被分配为 text/html MIME 类型,GIF 图像被分配为 image/gif MIME 类型,而 Microsoft Word 文档被分配为 application/msword MIME 类型。
浏览器使用 MIME 类型来确定如何处理页(或其他资源)。例如,如果浏览器从 Web 服务器获得一个具有可识别图像 MIME 类型的文件,则浏览器尝试将该文件解释并呈现为图像。如果浏览器获得一个具有 application/msword MIME 类型的文件,则该浏览器可能自动打开 Microsoft Word 以显示该文档(这里的确切行为取决于浏览器及其配置方式)。
W3C 为 XHTML 文档引入了一个 MIME 类型。这一新的 MIME 类型是 application/xhtml+xml。W3C 建议您在提供 XHTML 文档时使用 application/xhtml+xml MIME 类型,因为 XHTML 页应该以比旧式 HTML 页更严格的方式进行解释。
通过在页指令中包含 ContentType 属性,为 ASP.NET 页分配特定的 MIME 类型。例如,在 ASP.NET 页的顶部包含以下指令会导致为该页分配 application/xhtml+xml 类型。
<%@ ContentType="application/xhtml+xml" %>
W3C 的推荐标准有一个突出问题:并非所有浏览器都能识别 application/xhtml+xml。特别需要指出的是,Internet Explorer(有史以来最为流行的 Web 浏览器)不能识别 application/xhtml+xml MIME 类型。因此,使用推荐的 application/xhtml+xml MIME 类型提供 XHTML 页不是一个可行的选择。
有三种解决该问题的方式。可以使用 text/html MIME 类型来提供 XHTML 页,或者使用 application/xml(或 text/xml)MIME 类型来提供 XHTML 页,也可以使用内容协商方式。让我们对上述每个选择进行探讨。
第一个选择 — 以 text/html 类型提供页 — 是最容易的选择。默认情况下,ASP.NET 页被分配为该 MIME 类型。更好的做法是,按照 W3C 的建议,在向现有的 HTML 浏览器提供页时使用这一选择(请参阅 http://www.w3.org/TR/xhtml-media-types/)。如果创建的是 XHTML 1.0 Transitional 页,并且 Web 应用程序的主要受众使用不能理解 application/xhtml+xml MIME 类型的浏览器,那么以 text/html 类型提供页似乎十分明智。毕竟,引入 XHTML 1.0 Transitional 标准的目的是使开发人员能够更为容易地将现有的 HTML 页迁移到 XHTML。
这一主张是有争议的。例如,Ian Hickson 认为,绝不应该以 text/html 类型提供 XHTML 页,因为这样会导致随便的、不标准的 XHTML 页(请参阅 http://hixie.ch/advocacy/xhtml)。他建议作者们继续坚持使用 HTML 4.0,直到更多的浏览器完全支持 XHTML 标准为止。
第二个选择是使用 application/xml 或 text/xml MIME 类型,以 XML 类型提供 XHTML 页。在向 Internet Explorer 提供 XML 文档时,该文档会作为 XML 文档进行分析并呈现到浏览器中。(该文档由 document.XMLDocument 对象公开的 XML DOM 表示。)
以 XML 类型提供 XHTML 文档的优点是,XHTML 文档具有的任何问题都会被 Internet Explorer 的 XML 分析器捕获。例如,如果文档包含重叠标记,或者如果没有将属性的值包装到引号内,则不会呈现该文档,并且会显示错误信息(参见图 4)。XHTML 纯粹主义者认为该行为是一件好事,因为它可以防止您编写格式错误的 XHTML。
图 4. 在 Internet Explorer 中显示 XML
该方法的问题是:默认情况下,Internet Explorer 呈现 XML 文档的源代码。因此,如果以 XML 类型提供 XHTML 文档,则 Web 站点访问者将看到 XHTML 文档的源代码,而不是预期的呈现输出。W3C 推荐了一个用来解决该问题的“窍门”(请参阅 http://www.w3.org/MarkUp/2004/xhtml-faq#ie):如果通过使用 XSLT 转换将 XHTML 文档转换为 HTML,那么文档将分析为 XML 并显示为 HTML。
例如,清单 1 中的 ASP.NET 页将以 XML 文档的形式提供,但被转换为 HTML 文档。结果页会正确地显示在 Internet Explorer、Opera 和 Firefox 中。
清单 1. XMLPage.aspx
<%@ Page Language="VB" ContentType="text/xml" %> <?xml-stylesheet type="text/xsl" href="copy.xsl"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>My Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:TextBox ID="txtFirstName" runat="server" /> </div> </form> </body> </html>
页指令会导致该页以 text/xml 类型呈现。清单中的第二行引用了一个名为 copy.xsl 的 XSLT 样式表,它会对当前文档执行标识转换。换句话说,除了将原始XML 文档中的所有元素复制到新的 HTML 文档中以外,它根本没有做任何事情。copy.xsl 的源代码包含在清单 2 中。
清单 2. Copy.xsl
<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform"> <template match="/"> <copy-of select="."/> </template> </stylesheet>
该解决方案是有效的,但它似乎不是很精彩。当分析 XML 文档时,的确获得了额外的验证步骤。但是,如果在 Visual Studio .NET 2005 或 Visual Web Developer 中生成 ASP.NET 页,那么开发环境会在“Source”视图中执行相同的验证。最后,Internet Explorer 将收到与向它发送 text/html 类型文档时相同的文档。
第三个选择 — 内容协商,将 W3C 推荐标准的精神与最大程度的浏览器兼容性最佳地组合在一起(请参阅 http://www.w3.org/2003/01/xhtml-mimetype/content-negotiation)。当使用内容协商时,会以不同的 MIME 类型向不同的浏览器提供 ASP.NET 页。如果浏览器声称它支持 XHTML,则向它提供 XHTML 类型的页;否则,以 text/html MIME 类型向该浏览器提供页。
清单 3 中的 Global.asax 包含向不同的浏览器提供不同 MIME 类型页所需的代码。如果将该文件添加到 Web 项目中,则每个 ASP.NET 页的 MIME 类型都会随着每个请求而修改。将页提供给 Firefox 或 Opera 时,该页以 application/xhtml+xml 类型提供。另一方面,Internet Explorer 6 会收到 text/html 页。
清单 3. Global.asax
<script runat="server"> Sub Application_PreSendRequestHeaders(ByVal s As Object, _ ByVal e As EventArgs) If Array.IndexOf(Request.AcceptTypes, _ "application/xhtml+xml") > -1 Then Response.ContentType = "application/xhtml+xml" End If End Sub </script>
配置 XHTML 一致性
ASP.NET 2.0 框架的默认行为是呈现针对 XHTML 1.0 Transitional 能够通过验证的页。生成 Web 站点的大多数开发人员都希望面向该标准,因为它是与现有 HTML 页最为兼容的标准。但是,在某些情况下,该标准可能显得太松散或太严格。
例如,如果您志向远大,那您也许要生成 XHTML 1.0 Strict(甚至 XHTML 1.1)的 Web 站点。毕竟,XHTML 1.0 Transitional 标准的目标是充当通往这些更具限制性标准的跳板。默认情况下,因为 ASP.NET 2.0 框架面向 XHTML 1.0 Transitional,所以某些 ASP.NET 控件会呈现与 XHTML 1.0 Strict 或 XHTML 1.1 不兼容的属性。
而且,有时您还可能发现 XHTML 1.0 Transitional 标准的限制性过高。Microsoft 必须对现有 ASP.NET 1.1 控件进行多项更改才能符合 XHTML 1.0 Transitional 标准。其中一些更改可能会破坏现有的 ASP.NET 1.1 Web 站点。
为了满足每个人的要求,Microsoft 创建了一个名为 xhtmlConformance 的新配置选项,您可以在 Web 站点的配置文件中设置该选项。新的配置选项使您能够指定 Web 页的 XHTML 一致性的级别。它的内容如下所示。
<configuration> <system.web> <xhtmlConformance mode="transitional" /> </system.web> </configuration>
默认情况下,xhtmlConformance 设置为值 transitional。但是,还可以将该选项设置为值 strict 或 legacy。
如果将 xhtmlConformance 选项设置为 strict,那么标准的 ASP.NET 控件将不会再呈现某些属性。例如,ASP.NET <form> 控件将不再呈现 name 属性。除非 ASP.NET 页包含(不符合标准的)客户端脚本,否则从 transitional 模式切换到 strict 模式时,不会注意到任何变化。
如果将 xhtmlConformance 选项设置为 legacy,那么对于某些元素和属性(但不是全部),ASP.NET 框架将恢复为 ASP.NET 1.1 呈现行为。在这种情况下,ASP.NET 框架将呈现不与任何 XHTML 标准兼容的内容,并且页将不再通过 XHTML 标准验证。例如,在 legacy 模式下,呈现 <br> 标记时不会呈现它需要的 XHTML 结束斜杠 (<br />)。只有在将现有 ASP.NET 1.1 应用程序迁移到 ASP.NET 2.0 的过程中遇到问题时,将 xhtmlConformance 设置为 legacy 模式才是有意义的。
生成可访问的 ASP.NET Web 站点
遵守公共 Web 标准的好处是:它们使您以尽可能少地工作,使尽可能多的人能访问您的 Web 页。需要指出的是,可访问性标准使您能够生成可被残疾人士更容易访问的 Web 站点。
同样要强调的是,Web 站点用户中的相当一部分具有这样或那样的残疾。请试想一下您自己的家庭成员,并且考虑他们中有多少人会在与 Web 页交互时遇到麻烦。我就有一些上了年纪的亲戚是盲人或者失去了动作协调性。我猜测,本文的很多读者也有上了年纪的父母或祖父母,他们在使用大多数 Web 站点时会遇到很多困难。
生成可访问的 Web 站点有很多充分的理由:财务、道德、法律等等。但是,我们将重点讨论法律动机。在美国,按照康复法案 (Rehabilitation Act) 508 节的要求,联邦政府机构开发的任何 Web 站点都要使残疾人士可以访问。这一法律适用于联邦政府机构以及与联邦政府机构订立合同的公司(请参阅 http://www.section508.gov)。
其他国家/地区也具有类似的要求。例如,在加拿大,Treasury Board Common Look and Feel Standards 要求联邦政府机构开发的 Web 站点都要使残疾人士可以访问。在澳大利亚,Disability Discrimination Act 要求澳大利亚服务器上承载的所有 Web 站点(无论其是否是政府的 Web 站点)都要使残疾人士可以访问。(有关可访问性法律的详细信息,请参阅 http://www.w3.org/WAI/Policy。)
在我知道的 Web 站点开发人员中,没有任何人会故意生成残疾人士无法访问的 Web 站点。问题在于大多数开发人员都不熟悉各种可访问性标准。
在本文的下列各节中,将概述以下两个最重要的可访问性标准:WCAG 和 508 节标准。您还将学习如何通过使用 ASP.NET 控件生成可访问的 Web 页。最后,您将学习如何“验证”Web 页的可访问性。
可访问性标准
几乎所有可访问性标准和法律都源自 W3C Web Content Accessibility 1.0 Guidelines (WCAG)。这些准则是由 World Wide Web Consortium 在 1999 年 5 月 5 日作为推荐标准首次发布的(请参阅 http://www.w3.org/TR/WCAG10)。
WCAG 包含 14 条准则。每一条准则又包含一个或多个进一步阐明该准则的检查点。每个检查点都按 1 到 3 的优先级进行分级。为使这些准则的实施变得更加容易,W3C 已经发布了一组文档,其中包含有关如何遵守这些准则的技术(请参阅 http://www.w3.org/TR/WCAG10-TECHS/)。
您可以要求不同程度地遵守 WCAG 准则。如果要求 Web 站点满足所有优先级 1 的检查点,则您可以显示具有 Conformance Level A 的标识语。当 Web 站点满足所有优先级 1 和 2 检查点时,该 Web 站点可以显示 Conformance Level Double-A 标识语。最后,满足所有检查点的 Web 站点可以显示 Conformance Level Triple-A 标识语(请参阅 http://www.w3.org/WAI/WCAG1-Conformance.html)。
508 节准则源自 WCAG 准则。在美国,联邦政府机构(以及与联邦政府机构订立合同的公司)需要对这组准则给予最高程度的关注,因为这些准则具有法律效力。您可以在 508 节 Web 站点读到 508 节准则的完整文本。
ASP.NET 2.0 框架旨在使您能够满足所有 WCAG 优先级 1 和优先级 2 的检查点以及所有 508 节准则。这些准则使用起来非常严格。每个使用 ASP.NET 2.0 框架的开发人员都需要检查和测试每个 ASP.NET 控件的可访问性。而且,每个开发人员都应该在桌面上安装一个屏幕阅读器,以便针对这些准则测试页。
ASP.NET 2.0 中的可访问性改进
本文重点讨论 ASP.NET 2.0 框架中六个方面的可访问性改进。在下列各节中,您将学习如何使用 ASP.NET 控件来显示可访问的图像、表单、导航、数据和 XHTML。在本节结尾,我们还将考虑与在 ASP.NET 页中使用客户端脚本有关的可访问性问题。
创建可访问的图像
您不应当做这样的假设:与 Web 站点交互的每个人都可以实际看到您的 Web 站点。如果某个人是盲人或者视力不足,那么这个人就可能需要使用屏幕阅读器或盲文显示器来访问您的 Web 页。屏幕阅读器通过使用语音合成器来朗读 Web 页中的文本。盲文显示器将页中的文本转换为盲文表示。
对于无法看到它们的人而言,图像和其他非文本页元素(例如,Java、Shockwave 和 Flash 内容)都是没有用的。如果您希望使 Web 站点对于盲人或弱视的人是可访问的,那么需要为 Web 页中的所有非文本内容提供文本等效内容。
Web 页中的每个图像都应该包含 alt 属性。alt 属性用来表示由屏幕阅读器或其他辅助性设备阅读的替换文本。以下是 alt 属性的使用方式。
<img src="Products23.gif" alt="Image of Products" />
alt 属性应当包含图像的说明。在任何情况下,它都不应该只是包含该图像的文件名。alt 属性的目的是为盲人和视力正常的人传递相同的图像信息。写入 alt 属性的值时要求对该元素的含义进行人工解释。因此,不能自动完成创建 alt 属性的过程。
每个显示图像的 ASP.NET 控件都包含用于为该图像提供替换文本的方法。例如,ASP.NET 图像控件包含 AlternateText 属性。如果使用 Image 控件,则需要将 AlternateText 属性设置为有意义的值。
<asp:Image ImageUrl="Products23.gif" AlternateText="Image of Products" Runat="Server" />
如果某个图像只是用作设计元素,则应当将它的 alt 属性设置为空字符串。如果图像不具有需要传达的有用信息,那么就没有理由使屏幕阅读器的页解说变得散乱。
<img src="PageDivider.gif" alt="" />
在 ASP.NET 2.0 框架中,必须采取特殊措施,使您能够呈现空的 AlternateText。如果将空文本分配给 ASP.NET 控件的属性,则 ASP.NET 控件将根本不会呈现该属性。例如,假设将以下 ASP.NET Image 控件添加到页中。
<asp:Image ImageUrl="PageDivider.gif" AlternateText="" Runat="Server" />
在这种情况下,会呈现以下标记。
<img src="PageDivider.gif" style="border-width:0px;" />
请注意,alt 属性消失了。这是所有 ASP.NET 控件属性的默认行为。当没有为属性分配值时,该属性不会呈现出来。遗憾的是,在这种情况下,我们确实希望为 alt 属性呈现空值。
为了解决该问题,ASP.NET 2.0 框架中引入了以下新属性,使您能够用 Image 控件显示空替换文本:GenerateEmptyAlternateText 属性。
<asp:Image ImageUrl="PageDivider.gif" GenerateEmptyAlternateText="true" Runat="Server" />
如果使用 GenerateEmptyAlternateText 属性,则会正确地呈现 alt="" 属性。
当图像表示某个真正复杂的事物(例如,组织结构图)时,不能使用 alt 属性来提供替换文本说明。当需要提供较长的图像含义说明时,需要使用 longdesc 属性。
longdesc 属性接受相对或绝对 URL 作为它的值。该 URL 应当链接到包含图像内容的文本说明的页。以下示例说明如何将该属性与 <img> 标记配合使用。
<img src="OrgChart.gif" alt="Company Organization Chart" longdesc="/OrgChartDescription.aspx" />
ASP.NET Image 控件包含一个名为 DescriptionUrl 的属性,它对应于 HTML longdesc 属性。以下示例说明如何使用该属性。
<asp:Image ImageUrl="OrgChart.gif" AlternateText="Company Organization Chart" DescriptionUrl="/OrgChartDescription.aspx" Runat="server" />
创建可访问的表单
Web 页表单可能给视力低下的人士以及缺乏动作协调性的人士带来问题。如果通过屏幕阅读器访问 Web 页表单,那么可能很难将表单域与其相应的标签相关联。例如,假设 Web 页包含以下表单。
<table> <tr> <td>First Name:</td> <td><input name="txtFirstName" /></td> </tr> <tr> <td>Last Name:</td> <td><input name="txtLastName" /></td> </tr> </table>
该表单显示一个人的名和姓的输入域。在这种情况下,因为该表单显示在表中,所以屏幕阅读器用户可能很难将正确的标签与正确的表单域相关联。HTML 4.0 中引入以下新标记,以使您能够将表单域标签与表单域相关联:<label> 标记。下面说明如何使用 <label> 标记编写前面的表单。
<table> <tr> <td><label for="txtFirstName">First Name:</label></td> <td><input name="txtFirstName" id="txtFirstName" /></td> </tr> <tr> <td><label for="txtLastName">Last Name:</label></td> <td><input name="txtLastName" id="txtLastName" /></td> </tr> </table>
<label> 标记将表单域标签与其相应的表单域显式关联起来。请注意,<input> 域包含 id 属性,这是因为 for 属性的值必须是输入域的 id 属性而不是 name 属性。
通常,ASP.NET Label 控件生成 <span> 标记。但是,如果您在声明 ASP.NET Label 控件时提供了 AssociatedControlId 属性,则该控件会呈现 <label> 标记。下面说明如何用 ASP.NET Label 和 TextBox 控件生成可访问的表单。
<table> <tr> <td><asp:Label AssociatedControlID="txtFirstName" runat="server">First Name:</asp:Label></td> <td><asp:TextBox ID="txtFirstName" runat="server" /></td> </tr> <tr> <td><asp:Label AssociatedControlID="txtLastName" runat="server">Last Name:</asp:Label></td> <td><asp:TextBox ID="txtLastName" runat="server" /></td> </tr> </table>
在为 ASP.NET 控件提供标签时,应当使用 ASP.NET Label 控件,而不是 HTML <label> 标记。在将一个 ID 分配给 ASP.NET 控件(如 TextBox 控件)时,呈现到浏览器中的 ID 可能与您分配给该控件的 ID 不同。因此,如果使用 <label> 标记,则 <label> 标记中的 ID 可能与所呈现的 TextBox 控件的 ID 不匹配。另一方面,如果使用 ASP.NET Label 控件,则不必担心该问题。
ASP.NET CheckBox、RadioButton、CheckBoxList 和 RadioButtonList 控件自动呈现 <label> 标记。在使用这些控件时,请小心使用 Text 属性来标记控件的文本。您不应该执行以下操作。
<asp:CheckBox Runat="Server" /> Include Gift Wrap
相反,请执行以下操作。
<asp:CheckBox Text="Include Gift Wrap" Runat="Server" />
对于通过屏幕阅读器与 Web 页进行交互的用户,大型表单也可能产生问题。在聆听大型表单的内容时,很容易忘记正在聆听该表单的哪个部分。在显示大型表单时,将该表单划分为多个小块是一个好主意。您可以通过使用 <fieldset> 标记将单个表单划分为多个部分。以下示例说明如何使用该标记。
<form id="form1" runat="server"> <div> <fieldset> <legend>Contact Information</legend> ... form fields </fieldset> <fieldset> <legend>Payment Information</legend> ... form fields </fieldset> </div> </form>
该表单通过 <fieldset> 标记划分为两个子表单。<legend> 标记用来标记这些子表单的用途。在 Internet Explorer、Firefox 和 Opera 中显示时,这些子表单被边框直观地划分为多个单独的区域(参见图 5)。但是,重要的是要记住,<fieldset> 标记的主要用途是实现可访问性。如果不喜欢 <fieldset> 标记的可视化外观,那么可通过样式表规则修改该标记的外观,或通过使用 CSS display 或 visibility 属性将该标记完全隐藏。
图 5.
标记
视力低下的人士并不是 Web 页用户中唯一可能觉得 Web 表单难以访问的人。那些缺乏动作协调性的用户也会在与表单交互时遇到困难。
在生成 Web 表单时,为每个表单域包含 accesskey 和 tabindex 属性总是一个好主意。accesskey 属性使无法使用鼠标的用户能够直接导航到任何表单域。tabindex 属性使您能够控制表单域的 Tab 键顺序。对于那些必须通过键盘(或像键盘一样操作的辅助性设备)与页面进行交互的用户而言,这两个属性可使其生活变得更方便一些。
下面是一个同时使用 accesskey 和 tabindex 属性的示例表单。
<asp:Label AssociatedControlID="txtFirstName" AccessKey="f" runat="server"><u>F</u>irst Name</asp:Label> <asp:TextBox id="txtFirstName" TabIndex="1" Runat="server" /> <br /> <asp:Label AssociatedControlID="txtLastName" AccessKey="l" runat="server"><u>L</u>ast Name</asp:Label> <asp:TextBox id="txtLastName" TabIndex="2" Runat="server" />
tabindex 属性用来控制表单域的 Tab 键顺序。因为第一个表单域具有的 tabindex 值为 1,所以当用户第一次按 Tab 键时,该页中任何出现在该表单之前的其他元素都被跳过。
在使用 Internet Explorer 或 Firefox 时,按 ALT+F 可自动将焦点移至 First Name 文本框。如果按 ALT+L,则焦点会自动移至 Last Name 文本框。在使用 Opera 时,必须首先按 SHIFT+ESC,然后才能选择访问键。
请注意,First Name 和 Last Name 标签的第一个字母都带有下划线。通过为字母添加下划线,可以为 Web 站点的用户提供访问键的直观表示。这是在 Microsoft Windows 应用程序中标记访问键的标准方式。但是,还有其他在表单中指示访问键的推荐方法(请参阅 http://www.cs.tut.fi/~jkorpela/forms/accesskey.html)。
使用下划线指示访问键的一个问题是无法为按钮中的字符添加下划线,并且超链接已经带有下划线。例如,下面的 Button 控件并不像您预期和希望的那样工作。
<asp:Button Text="<u>S</u>ubmit" Runat="server" />
在呈现该 ASP.NET Button 控件时,会显示实际文本 Submit,而不是显示带下划线的<u>S</u>字符。ASP.NET Button 控件呈现 HTML<input type="submit"> 标记,但遗憾的是, <input type="submit">标记不支持下划线。
您可能认为可以通过使用样式规则解决该问题。遗憾的是,当前不存在以下这种跨浏览器兼容方法:即,使用层叠样式表为 <input type="submit">标记中的单个字符加下划线。
如果您愿意在页中使用客户端 JavaScript,则可以解决该问题。清单 4 中的页包含的 JavaScript 根据是否按下 ALT 键而显示或隐藏所有访问键。当按下 ALT 键时,会弹出一个框,显示访问键键盘组合键(参见图 6)。该脚本在 Internet Explorer 和 Firefox 中都能够正常工作(Opera 不使用 ALT 键来选择访问键)。
图 6. AccessKeys.aspx
清单 4. AccessKeys.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Contact Form</title> <style type="text/css"> .accessKey { display:none; position:absolute; z-index:5000; padding:3px; border:solid 1px black; background-color: #ffffe0 } </style> <script type="text/javascript"> /* <![CDATA[ */ window.onload = function() { document.onkeydown = displayAccessKeys; } function displayAccessKeys(e) { if (!e) e = window.event; if (e.keyCode == 18) { toggleAccessKeys(); document.onkeydown = null; document.onkeyup = hideAccessKeys; } } function hideAccessKeys(e) { if (!e) e = window.event; if (e.keyCode == 18) { toggleAccessKeys(); document.onkeyup = null; document.onkeydown = displayAccessKeys; } } function toggleAccessKeys() { var spans = document.getElementsByTagName('span'); for (var k=0;k<spans.length;k++) if (spans[k].className == 'accessKey' ) { if ( 'inline' != spans[k].style.display) spans[k].style.display = 'inline'; else spans[k].style.display = 'none'; } } /* ]]> */ </script> </head> <body> <form id="form1" runat="server"> <div> <table> <tr> <td> <asp:Label ID="lblFirstName" AssociatedControlID="txtFirstName" AccessKey="f" runat="server">First Name</asp:Label> </td> <td> <asp:TextBox ID="txtFirstName" runat="server" /> <span class="accessKey">access key is f</span> </td> </tr> <tr> <td> <asp:Label ID="lblLastName" AssociatedControlID="txtLastName" AccessKey="l" runat="server">Last Name:</asp:Label> </td> <td> <asp:TextBox ID="txtLastName" runat="server" /> <span class="accessKey">access key is l</span> </td> </tr> <tr> <td colspan="2"> <asp:Button Text="Submit" runat="server" /> <span class="accessKey">access key is s</span> </td> </tr> </table> </div> </form> </body> </html>
清单 4 中的页包含样式表和客户端 JavaScript。样式表隐藏了由 accessKey 类标识的任何 <span> 标记的内容。JavaScript 会在 ALT 键已经被按下时进行检测,并且显示 <span> 标记的内容。
请注意,即使 Web 浏览器中禁用了样式表和 JavaScript,该页也能够正常工作。在这种情况下,将总是显示访问键帮助(参见图 7)。
图 7. AccessKeys.aspx 适度降格
创建可访问的导航
我讨厌拨打客户支持电话并按照自动系统的指示操作。当计算机语音系统用其低沉单调的声音宣布每个选项时,我感觉自己正在慢慢地变老。如果按错了一个键,那么您就会永远迷失在自动计算机系统深不可测的迷宫中。
遗憾的是,如果您被迫使用屏幕阅读器,那么这正是您在访问几乎任何 Web 页时的体验。大多数 Web 站点都在每一页中包含一个导航栏,其中包含指向 Web 站点各个部分的链接列表。如果使用屏幕阅读器,则每当您打开页时,都必须逐个聆听这些导航链接中的各个链接。
通过对导航栏进行一处简单的修改,就可显著提高 Web 页的可访问性。只需添加一个用来跳过所有导航链接的方法。可以用“跳过导航”链接完成该工作。
例如,CNN Web 站点包含一个导航栏,其中列出了 CNN Web 站点的不同部分(World、U.S.、Weather 等等)。但是,CNN Web 站点的设计人员已经做了一件聪明的事情。如果查看页的源代码,则您将注意到导航栏上会出现以下链接。
<a HREF="#ContentArea" TARGET="_self"> <img src="http://i.cnn.net/cnn/images/1.gif" alt="Click here to skip to main content." width="10" height="1" border="0" align="right"></a>
当查看 CNN Web 站点的主页时,您绝对不会看到该链接。该链接中包含的图像是一幅透明的单像素图像。但是,如果您用屏幕阅读器访问该页,则会阅读与该图像相关联的替换文本。盲人可以选择跳过所有导航链接,并直接移至 Web 页的主要内容区域(这与在自动语音系统中按 0 并直接导航到话务员等效)。
“跳过导航”链接已经被集成到多个标准 ASP.NET 2.0 控件中。特别需要指出的是,Menu、TreeView、SiteMapPath、Wizard 和 CreateUserWizard 控件全都支持“跳过导航”链接。
例如,清单 5 中的页包含 ASP.NET Menu 控件。该控件用来显示指向该 Web 站点中其他页的链接列表。
清单 5. SiteMenu.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Skip Navigation</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Menu id="Menu1" Runat="server"> <Items> <asp:MenuItem Text="Home" NavigateUrl="Home.aspx" /> <asp:MenuItem Text="Products" NavigateUrl="Products.aspx" /> <asp:MenuItem Text="Services" NavigateUrl="Services.aspx" /> <asp:MenuItem Text="About" NavigateUrl="About.aspx" /> </Items> </asp:Menu> <hr /> Here is the main content of the page... </div> </form> </body> </html>
如果查看清单 5 中页的源代码,您将看到以下链接出现在菜单顶部。
<a HREF="#Menu1_SkipLink" TARGET="_self"><img alt="Skip Navigation Links" src="/WebResource.axd?d=ChXz41GuDxNm-7TcWyCl_w2&t=632495684475122400" width="0" height="0" style="border-width:0px;" />
该链接包含一幅在您查看该页时不会出现的宽和高皆为零的图像。但是,通过屏幕阅读器访问该页的用户可以选择“跳过导航”链接跳到该菜单的结尾。
默认情况下,“跳过导航”链接包含文本 Skip Navigation Links。可以通过更改 Menu 控件的 SkipLinkText 属性修改该值。
创建可访问的数据
ASP.NET 2.0 框架包含一组丰富的、用于显示数据库数据的控件。这些控件包括 GridView、DetailsView、DataList、FormView 和 Repeater 控件。默认情况下,GridView、DetailsView 和 DataList 控件在 HTML 表中显示数据库记录。
在 HTML 表中呈现信息时,如果操作错误,则可能引起可访问性问题。在聆听 HTML 表的内容时,您很容易忘记自己当前在该表中的位置。例如,假设您使用 HTML 表显示一个产品信息列表。在聆听由屏幕阅读器朗读的表内容时,您很容易将某个表单元格所代表的信息搞混,不知道它们是有关产品名称的,还是有关所订购产品数量的,抑或是有关存储这些产品的仓库的代码。
在查看 HTML 表时,可通过扫视列或行标题来确定特定单元格的含义。为使表对于使用屏幕阅读器的用户是可访问的,需要显式标记表标题并将这些标题与各个单元格显式关联起来。
在创建表以显示数据时,应当始终使用正确的标记来标记列和行标题。表标题应当总是用 <th> 标记进行标记,如下所示。
<table> <thead> <tr> <th>Product Name</th> <th>Price</th> </tr> </thead> <tbody> <tr> <td>Milk</td> <td>$2.33</td> </tr> <tr> <td>Cereal</td> <td>$5.61</td> </tr> </tbody> </table>
在该示例中,<th> 标记用来标记以下两个列标题:Product Name 和 Price。
一些设计人员避免使用 <th> 标记,因为他们不喜欢它的默认可视化外观。在大多数浏览器中,<th> 标记的内容居中并且加粗。但是,需要记住的是,标记绝不应当用来控制表示形式。如果您希望列标题看起来像标准的表单元格,则您应当添加如下所示的样式规则。
<style type="text/css"> th {text-align:left;font-weight:normal} </style>
为了使表可访问,还应当显式指明与各个单元格相关联的一个或多个标题。您可以将多个属性用于此目的:scope、headers 和 axis。
scope 属性可用来指示表标题是列标题还是行标题。例如,下面的表同时包含列标题和行标题,它们都通过使用 scope 属性的 <th> 标记进行标记。
<table> <thead> <tr> <th></th> <th scope="col">First Train</th> <th scope="col">Last Train</th> </tr> </thead> <tbody> <tr> <th scope="row">Alewife</th> <td>5:24am</td> <td>12:15am</td> </tr> <tr> <th scope="row">Braintree</th> <td>5:15am</td> <td>12:18am</td> </tr> </tbody> </table>
该表包含 Boston 地铁 Red Line 的时间表(参见图 8)。请注意,每个列标题都包含 scope="col" 属性,而每个行标题都包含 scope="row" 属性。
图 8. 简单的地铁时间表
scope 属性非常适合于简单的表。但是,对于更为复杂的表,需要使用 headers 属性。例如,嵌套表可能有三个或更多的标题与单个单元格相关联。headers 属性使您能够用与各个单元格相关联的标题来标记它。
axis 属性使您能够对表标题进行分类。例如,在地铁时间表中,可以将属性 axis="location" 添加到每个表示位置的标题(Alewife 和 Braintree 标题)中。axis 属性接受由逗号分隔的类别列表。
清单 6 中的页包含一个更复杂版本的 Boston 地铁时间表,它同时使用了 headers 和 axis 属性(参见图 9)。