跟着 MDN 学无障碍 Day 4:HTML 无障碍技能测试实战

在前一篇文章中,我们系统学习了 HTML 语义化对无障碍的重要性。本文将通过四个实战测试题目,帮助开发者检验和巩固对 HTML 无障碍知识的掌握程度。每个任务都对应一个实际开发中常见的场景,从信息面板到表单、链接再到图片画廊,涵盖了 HTML 无障碍的核心知识点。

一、任务一:修复信息面板的语义结构

第一个任务要求我们修改一段信息面板的 HTML 代码。原始代码使用了 font 标签和换行符来模拟标题和段落结构,完全忽略了语义化的重要性。

原始代码分析

原始代码如下所示:

html 复制代码
<font size="7">Need help?</font> <br /><br />
If you have any problems with our products, our support center can offer you all
the help you need, whether you want:
<br /><br />
1. Advice choosing a new product
<br />
2. Tech support on an existing product
<br />
3. Refund and cancellation assistance
<br /><br />
<font size="5">Contact us now</font>
<br /><br />
Our help center contains live chat, email addresses, and phone numbers.
<br /><br />
<div class="button">Find Contact Details</div>
<br />
<font size="5">Find out answers</font>
<br /><br />
Our Forums section contains a large knowledge base of searchable previously
asked questions, and you can always ask a new question if you can't find the
answer you're looking for.
<br /><br />
<div class="button">Access Forums</div>

这段代码存在多个无障碍问题。font 标签已经被废弃,不应该在现代 HTML 中使用。标题应该使用 h1h6 元素来表达层级关系。列表项使用数字加换行符手动编号,而应该使用有序列表 ol。按钮使用 div 模拟,缺乏键盘交互支持。

正确的语义化改写

修复后的代码应该使用正确的语义元素:

html 复制代码
<h1>Need help?</h1>

<p>If you have any problems with our products, our support center can offer you all the help you need, whether you want:</p>

<ol>
  <li>Advice choosing a new product</li>
  <li>Tech support on an existing product</li>
  <li>Refund and cancellation assistance</li>
</ol>

<h2>Contact us now</h2>

<p>Our help center contains live chat, email addresses, and phone numbers.</p>

<button class="button">Find Contact Details</button>

<h2>Find out answers</h2>

<p>Our Forums section contains a large knowledge base of searchable previously asked questions, and you can always ask a new question if you can't find the answer you're looking for.</p>

<button class="button">Access Forums</button>

知识点解析

这个任务主要考察三个关键知识点。第一,标题层级的使用。h1 用于页面主标题,h2 用于二级标题,形成清晰的文档大纲。屏幕阅读器用户可以通过标题列表快速了解页面结构并跳转到感兴趣的部分。

第二,有序列表的使用。列表项使用 olli 标记后,屏幕阅读器会朗读"列表,共 3 项"以及当前项序号,让用户清楚知道列表的整体规模和当前位置。手动编号虽然视觉上看起来一样,但失去了语义信息。

第三,按钮元素的正确使用。button 标签提供了内置的键盘支持,用户可以通过 Tab 键聚焦、回车键或空格键激活。而 div 模拟的按钮即使通过 CSS 看起来一样,也无法提供这些交互能力。

二、任务二:完善表单的标签与分组

第二个任务涉及一个包含三个输入字段的表单。原始代码虽然视觉上看起来正常,但在语义关联和分组方面存在明显缺陷。

原始代码分析

html 复制代码
<form>
  <ul>
    <li>
      Name
      <input type="text" name="name" />
    </li>
    <li>
      Age
      <input type="number" name="age" />
    </li>
    <li>
      Email address
      <input type="email" name="email" />
    </li>
  </ul>
</form>

这段代码的问题在于标签和输入框之间缺乏明确的语义关联。虽然文字显示在输入框旁边,但屏幕阅读器无法确认这段文字是否就是该输入框的标签。当用户聚焦到输入框时,屏幕阅读器可能只朗读"编辑文本"而不知道应该输入什么内容。

正确的表单标记方法

修复后的代码需要建立明确的标签关联,并对相关字段进行分组:

html 复制代码
<form>
  <fieldset>
    <legend>Personal data</legend>
    <ul>
      <li>
        <label for="name">Name</label>
        <input type="text" id="name" name="name" />
      </li>
      <li>
        <label for="age">Age</label>
        <input type="number" id="age" name="age" />
      </li>
      <li>
        <label for="email">Email address</label>
        <input type="email" id="email" name="email" />
      </li>
    </ul>
  </fieldset>
</form>

知识点解析

这个任务涉及三个核心知识点。首先是 labelinput 的关联。通过为 input 设置 id 属性,并在 label 中使用 for 属性指向该 id,建立明确的语义关联。这样屏幕阅读器在聚焦到输入框时会朗读对应的标签文本,用户能够清楚知道需要输入什么内容。点击标签文本也会自动聚焦到对应的输入框,增大了可操作区域。

其次是 fieldset 分组的使用。fieldset 元素可以将相关表单控件组织在一起,表明它们属于同一逻辑组。这对于包含多个部分的复杂表单尤其重要,让屏幕阅读器用户能够理解字段之间的归属关系。

第三是 legend 标题的作用。legendfieldset 的标题,描述整个分组的主题。在这个任务中,使用 "Personal data" 作为分组标题,概括了姓名、年龄和邮箱这三个字段的共同属性。屏幕阅读器在进入分组时会朗读这个标题,让用户快速了解这组输入框的整体用途。

三、任务三:创建信息丰富的可访问链接

第三个任务要求修改段落中的四个链接,让它们对屏幕阅读器用户和视力正常的用户都更加友好。

原始代码分析

html 复制代码
<p>
  For more information about our activities, check out our fundraising page
  (<a href="/fundraising" target="_blank">click here</a>), education page
  (<a href="/education" target="_blank">click here</a>), sponsorship pack
  (<a href="/resources/sponsorship.pdf" target="_blank">click here</a>),
   and assessment sheets
  (<a href="/resources/assessments.docx" target="_blank">click here</a>).
</p>

这段代码的主要问题是所有链接都使用 "click here" 作为链接文本。屏幕阅读器用户可以调出页面上的所有链接列表,"click here" 会重复出现多次,用户无法通过链接文本判断每个链接的目的地。此外,对于 PDF 和 Word 文档这样的特殊文件类型,用户需要提前知道文件格式和大小才能决定是否点击。

优化后的链接实现

修复后的代码应该为每个链接提供有意义的描述性文本,并告知用户特殊文件的信息:

html 复制代码
<p>
  For more information about our activities, check out our 
  <a href="/fundraising">fundraising page</a>, 
  <a href="/education">education page</a>, 
  <a href="/resources/sponsorship.pdf">sponsorship pack (PDF, 8MB)</a>, 
  and <a href="/resources/assessments.docx">assessment sheets (Word document)</a>.
</p>

知识点解析

这个任务考察了两个重要知识点。第一个是链接文本的可理解性。链接文本应该清晰描述链接的目标,而不是使用 "click here"、"read more" 等无意义的短语。当屏幕阅读器用户浏览链接列表时,"fundraising page"、"education page" 这样的文本能够让用户快速找到所需内容。对于视力正常的用户,描述性链接文本也增加了可读性,用户无需阅读周围的上下文就能理解链接的用途。

第二个知识点是特殊文件类型的提示。对于非 HTML 资源,如 PDF、Word 文档、大文件等,应当在链接文本中明确告知用户。这样用户可以在点击之前判断自己是否有能力查看该文件,避免因格式不兼容或下载时间过长而浪费流量和时间。提示信息可以放在链接文本中,也可以使用括号补充说明,如 "(PDF, 8MB)" 或 "(Word document)"。

关于 target="_blank" 的使用,虽然原始代码中使用了这个属性让链接在新标签页中打开,但从无障碍角度考虑,应该让用户自行控制是否在新窗口中打开页面。如果确实需要在新窗口打开,应该通过链接文本提前告知用户,例如 "fundraising page (opens in new tab)"。

四、任务四:修复图片画廊的无障碍问题

第四个任务涉及一个图片画廊,其中包含标题图片和画廊图片,两者都存在无障碍问题需要修复。

原始代码分析

html 复制代码
<header>
  <img
    src="https://mdn.github.io/shared-assets/images/examples/star-pink_32x32.png"
    alt="A star that I use to decorate my page" />
  <h1>Groovy images</h1>
</header>
<main>
  <img
    src="https://mdn.github.io/shared-assets/images/examples/ballon-portrait.jpg" />
  <img
    src="https://mdn.github.io/shared-assets/images/examples/grapefruit-slice.jpg" />
</main>

这段代码存在两个问题。标题图片的 alt 文本描述的是"我用来装饰页面的星星",这属于作者的个人背景信息,对用户理解页面没有帮助。如果该图片仅用于装饰,应该使用空的 alt 属性。画廊图片则完全没有提供 alt 属性,屏幕阅读器会读出文件名作为替代,这对用户毫无意义。

修复后的实现方案

对于画廊图片,需要为每张图片提供有意义的 alt 文本:

html 复制代码
<header>
  <img
    src="https://mdn.github.io/shared-assets/images/examples/star-pink_32x32.png"
    alt="" />
  <h1>Groovy images</h1>
</header>
<main>
  <img
    src="https://mdn.github.io/shared-assets/images/examples/ballon-portrait.jpg"
    alt="Red balloon floating in a blue sky" />
  <img
    src="https://mdn.github.io/shared-assets/images/examples/grapefruit-slice.jpg"
    alt="A slice of pink grapefruit on a white plate" />
</main>

对于标题图片,更好的做法是使用 CSS 将其实现为背景图像,这样它就不会出现在 DOM 中,也不会对屏幕阅读器产生任何干扰:

css 复制代码
header {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 20px;
}

header::before {
  content: "";
  display: inline-block;
  width: 32px;
  height: 32px;
  background-image: url("https://mdn.github.io/shared-assets/images/examples/star-pink_32x32.png");
  background-size: contain;
}

知识点解析

这个任务涉及三个关键知识点。首先是装饰性图片的处理。如果图片仅用于视觉装饰而不传达任何信息内容,应该使用空的 alt 属性。这样屏幕阅读器会忽略该图片或仅提示"图像"而不朗读任何描述,用户不会被无关元素干扰。更优的做法是使用 CSS 背景图像,让装饰元素完全脱离内容层。

其次是内容图片的替代文本。对于传达信息的图片,alt 属性应该提供简洁准确的描述,让无法看到图片的用户获得等价的信息。这个任务中,"Red balloon floating in a blue sky" 描述了气球的颜色、状态和背景环境,"A slice of pink grapefruit on a white plate" 描述了水果的种类、颜色和展示方式。alt 文本应该客观描述视觉内容,而非添加作者的主观感受。

第三是语义元素的补充。虽然在原始代码中 header 使用了 imgh1 的组合,但实际上述标题图片完全可以通过 CSS 实现,这样更符合内容与表现分离的原则。当图片纯粹用于装饰性目的时,将其移出 HTML 内容层是更干净的做法。

五、综合总结

通过这四个实战任务,我们全面检验了 HTML 无障碍的核心知识点。任务一强调了标题层级、列表结构和按钮元素的语义化使用。任务二展示了表单标签关联和字段分组的重要性。任务三说明了链接文本的描述性和特殊文件信息的提示。任务四则涵盖了装饰性图片和内容图片的替代文本处理。

这些技能在实际开发中具有直接的指导意义。每个任务都对应一个常见的开发场景,修复这些问题并不需要复杂的技巧,只需要坚持使用正确的 HTML 元素并为其提供必要的语义信息。无障碍设计不是一项额外的工作负担,而是高质量 Web 开发的基本要求。通过持续关注和优化 HTML 语义化,我们可以让网页真正服务于所有用户。