HTML 元素超过 100 个,并且能够创建自定义元素,因此您可以通过无数种方式标记内容。不过,有些方式(尤其是语义化)比其他方式更好。
语义是指“与含义相关”。编写语义 HTML 意味着使用 HTML 元素根据每个元素的含义(而非外观)来构建内容。
本系列文章尚未介绍许多 HTML 元素,但即使不了解 HTML,您也可以通过以下两个代码段了解语义标记如何为内容提供上下文。两者都使用字数而非 ipsum lorem 来节省一些滚动操作,请发挥您的想象力,将“三十个字”扩展为 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</div>
<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>
<h2>five words</h2>
</header>
<section>
<h2>three words</h2>
<p>forty-six words</p>
<p>forty-four words</p>
</section>
<section>
<h3>seven words</h3>
<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 无障碍功能面板中的呈现方式:


在图 2 中,第二个代码块中有四个地标角色。它使用方便命名的语义地标 <header>
、<main>
、<footer>
和 <nav>
进行“导航”。位置标记可为网页内容提供结构,并有助于指明内容的重要部分,以便屏幕阅读器用户通过键盘进行浏览。
当 <header>
和 <footer>
未嵌套在其他地标中时,它们分别是角色为 banner
和 contentinfo
的地标。Chrome 的 AOM 会显示如下内容:


查看 Chrome 开发者工具,您会发现使用语义元素时与不使用语义元素时,无障碍对象模型存在显著差异。
很明显,使用语义元素有助于实现无障碍功能,而使用非语义元素会降低无障碍功能。HTML 通常默认情况下是可访问的。作为开发者,我们的工作既要保护 HTML 的默认可访问性,又要最大限度地提高用户的可访问性。您可以在开发者工具中检查 AOM。
role
属性
role
属性用于描述元素在文档上下文中的角色。role
属性是一个全局属性,这意味着它对所有元素都有效。该属性由 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 的掌握情况。
您应始终将 role="button"
添加到 <button>
元素。
<button>
元素已具有此角色。