语义 HTML

我们提供超过 100 个 HTML 元素以及创建自定义元素的能力,标记您的内容的方法不计其数;但某些方式(特别是语义)优于其他方式。

语义是指“与含义相关”。编写语义 HTML 是指使用 HTML 元素根据每个元素的含义(而非其外观)来构建内容。

本系列文章尚未介绍很多 HTML 元素,但即使不了解 HTML,以下两个代码段也展示了语义标记如何提供内容上下文。两者都使用字数统计而不是 ipsum lorem,以节省一些滚动时间。请发挥想象力,将“30 个字”扩展为 30 个字词:

第一个代码段使用 <div><span>,这两个元素没有语义值。

<div>
  <span>Three words</span>
  <div>
    <a>one word</a>
    <a>one word</a>
    <a>one word</a>
    <a>one word</a>
  </div>
</div>
<div>
  <div>
    <div>five words</div>
  </div>
  <div>
    <div>three words</div>
    <div>forty-six words</div>
    <div>forty-four words</div>
  </div>
  <div>
    <div>seven words</h2>
    <div>sixty-eight words</div>
    <div>forty-four words</div>
  </div>
</div>
<div>
   <span>five words</span>
</div>

您能看出这些字词的扩展含义吗?显然不会

我们用语义元素重写此代码:

<header>
  <h1>Three words</h1>
  <nav>
    <a>one word</a>
    <a>one word</a>
    <a>one word</a>
    <a>one word</a>
  </nav>
</header>
<main>
  <header>
    <h1>five words</h1>
  </header>
  <section>
    <h2>three words</h2>
    <p>forty-six words</p>
    <p>forty-four words</p>
  </section>
  <section>
    <h2>seven words</h2>
    <p>sixty-eight words</p>
    <p>forty-four words</p>
  </section>
</main>
<footer>
  <p>five words</p>
</footer>

哪个代码块表达了含义?仅使用 <div><span> 的非语义元素,您无法判断第一个代码块中的内容代表什么。第二个包含语义元素的代码示例为非编码器提供了足够的上下文,无需遇到 HTML 标记即可解读其用途和含义。它无疑提供了足够的背景信息,即使开发者不理解网页内容(例如非英语内容),也能让他们了解网页内容。

在第二个代码块中,即使不了解内容,我们也可以了解架构,因为语义元素提供了意义和结构。您可以看出,第一个标头是网站的横幅,其中 <h1> 可能是网站名称。页脚就是网站页脚:这五个字词可能是版权声明或公司地址。

语义标记不仅能让标记更易于开发者阅读,更重要的是它能让自动化工具轻松解读标记。开发者工具也展示了语义元素如何提供机器可读的结构。

无障碍对象模型 (AOM)

浏览器在解析收到的内容时,会构建文档对象模型 (DOM) 和 CSS 对象模型 (CSSOM)。然后,它还构建了一个无障碍功能树。辅助设备(如屏幕阅读器)使用 AOM 解析和解释内容。DOM 是文档中所有节点的树。AOM 就像是 DOM 的语义版本。

我们来比较一下这两种文档结构在 Firefox 的无障碍功能面板中的呈现方式:

全部为链接或文本叶的节点列表。
第一个代码段。
包含清晰地标的节点列表。
第二个代码段。

在第二个屏幕截图中,第二个代码块中有四个地标角色。它使用语义地标(方便地命名为 <header><main><footer><nav>)来表示“导航”。地标可为网页内容提供结构,并确保屏幕阅读器用户可通过键盘轻松浏览重要内容部分。

请注意,<header><footer> 是地标,当它们未嵌套在其他地标中时,它们分别具有 bannercontentinfo 角色。Chrome 的 AOM 如下所示:

所有文本节点均以静态文本形式列出。
第一个代码段。
文本节点都包含说明。
第二个代码段。

查看 Chrome 开发者工具时,您会注意到使用语义元素与不使用语义元素时的无障碍对象模型之间存在显著差异。

很明显,语义元素有助于实现无障碍功能,而使用非语义元素会降低无障碍功能。通常情况下,HTML 通常可以访问。作为开发者,我们的职责是保护 HTML 的默认可访问性,并确保提供最大程度的可访问性。您可以在开发者工具中检查 AOM

role 属性

role 属性描述元素在文档上下文中的作用。role 属性是一个全局属性,意味着它对所有元素有效。ARIA 规范由 ARIA 规范定义,而不是由 WHATWG HTML 规范定义;在本规范系列中,几乎所有其他内容都已定义。

每个语义元素都有隐式角色,有些取决于上下文。正如我们在 Firefox 无障碍功能开发者工具屏幕截图中看到的,顶层 <header><main><footer><nav> 都是地标,而嵌套在 <main> 中的 <header> 则是一个部分。Chrome 屏幕截图列出了这些元素的 ARIA 角色<main>main<nav>navigation<footer>(因为它是文档页脚)为 contentinfo。当 <header> 是文档的标头时,默认角色为 banner,这样会将此部分定义为全局网站代码。如果 <header><footer> 嵌套在版块元素中,则它不是地标角色。这两种开发者工具的屏幕截图都展示了这一点。

元素角色名称在构建 AOM 时非常重要。元素的语义(即“角色”)对于辅助技术和(在某些情况下)搜索引擎非常重要。辅助技术用户依靠语义来导航并了解内容的含义。此元素的角色可让用户快速访问其查找的内容,更重要的是,此角色可告知屏幕阅读器用户在某个互动元素获得焦点后该如何与其互动。

互动元素(如按钮、链接、范围和复选框)都具有隐式角色,所有元素都会自动添加到键盘 Tab 键序列中,并且都具有默认预期的用户操作支持。隐式角色或显式 role 值会告知用户是特定于元素的默认用户互动。

使用 role 属性,您可以为任何元素分配角色,包括不同于标记所暗示的角色。例如,<button> 具有 button 的隐式角色。借助 role="button",您可以在语义上将任何元素转换为按钮:<p role="button">Click Me</p>

虽然向元素添加 role="button" 会告知屏幕阅读器该元素是一个按钮,但这不会更改该元素的外观或功能。button 元素提供了许多功能,您无需执行任何操作。button 元素会自动添加到文档的标签页排序序列中,这意味着默认情况下该元素可通过键盘聚焦。Enter 键和空格键均可激活该按钮。按钮还具有 HTMLButtonElement 接口为其提供的所有方法和属性。如果您没有为按钮使用语义按钮,则必须重新编程所有这些功能。使用 <button> 简单得多。

返回非语义代码块的 AOM 屏幕截图。您会注意到,非语义元素没有隐式角色。我们可以为每个元素分配一个角色,从而创建非语义版本语义:

<div role="banner">
  <span role="heading" aria-level="1">Three words</span>
  <div role="navigation">
    <a>one word</a>
    <a>one word</a>
    <a>one word</a>
    <a>one word</a>
  </div>
</div>

虽然 role 属性可用于向任何元素添加语义,但您应改用具有所需隐式角色的元素。

语义元素

如果问自己:“哪个元素最能代表这部分标记的功能?”通常可让您选择最适合该工作的元素。由于标签具有语义含义,因此您选择的元素以及您使用的标签应当适合您显示的内容。

HTML 应该用于设计内容的结构,而不是定义内容的外观。外观是 CSS 的一大重点。尽管某些元素被定义为以某种特定方式显示,但请不要根据用户代理样式表让相应元素默认显示的方式而使用某个元素。而应根据元素的语义含义和功能选择各个元素。以逻辑、语义且有意义的方式对 HTML 进行编码有助于确保 CSS 按预期应用。

以编码方式为作业选择合适的元素,这意味着您无需重构 HTML 或为 HTML 添加注释。考虑对作业使用正确的元素时,通常都是为作业选择合适的元素。否则,您很可能不会这样做。如果您了解每个元素的语义,也理解了选择正确元素的重要性,那么您通常也能做出正确的选择,而无需花费太多精力。

在下一部分中,您将使用语义元素来构建文档结构

检查您的掌握程度

测试您对语义 HTML 的了解程度。

您应始终将 role="button" 添加到 <button> 元素中。

错误。
正确!<button> 元素已具有此角色。
正确。
请重试。