HTML5的语义元素

Published on 2016 - 08 - 31

从Web诞生到现在的20年间,网站发生了天翻地覆的变化。不过,最让人叹为观止的,还不是Web的变化有多大,而是最古老的HTML元素到今天依然被沿用着!事实上,Web开发人员在构建现代网站时使用的HTML元素,与10年前构建网站时使用的HTML元素别无二致。

有一个元素特别值得一提,那就是温和谦恭的<div>(division,分区)元素,它堪称每一个现代网页的柱石。利用<div>元素,可以把整个HTML文档分隔为页眉、侧边面板、导航条,等等。再辅以少量可靠的CSS,就可以把这些区块转换成带边框的盒子或带阴影的分栏,而且各就各位。

这种<div>加样式的技术既简明又强大,还非常灵活——但不够透明。这句话的意思是,在查看别人的源代码时,必须费点劲才能知道哪个<div>表示什么,而整个页面又是怎么搭建起来的。为了理解页面的构造,不得不在标记、样式表和浏览器的实际页面之间跳来转去。特别是在破解别人编写的不怎么符合最佳实践的页面时,即便你也在自己的网站中应用了同样的设计技术,也少不了会面对这种困惑。

这种情况引发了人们的思考。是不是可以用更好的东西来代替<div>?这种东西需要发挥与<div>一样的作用,但却能传达出更多的语义。而且,要能够把侧边栏与页眉分开,以及把广告条与菜单分开。HTML5为此引用了一组构造页面的新元素,实现了Web开发人员的这一夙愿。

语义元素

要想让网页的结构更清晰,需要使用HTML5中新的语义元素(semantic element)。这些元素可以为它们标注的内容赋予额外的含义。

例如,新的<time>元素用于在网页中标注一个有效的日期或时间。下面就是<time>元素最简单的用例:

Registration begins on <time>2012-11-25</time>.

这行代码在网页中呈现的结果如下所示:

Registration begins on 2012-11-25.

最关键的是要理解,<time>元素没有任何内置的样式。实际上,网页的读者也没有办法知道有一个额外的元素包含了日期。你可以使用样式表为<time>元素添加样式,但默认情况下,它包含的内容与普通文本没有任何区别。

设计<time>元素的用意是让它来包含一小段信息。不过,大多数HTML5的语义元素可不是这样的,那些元素的用途是标识页面中的一个内容区块。比如,<nav>元素用于标识一组导航链接。而<footer>元素用于标识通常放在页面底部的文脚(或页脚)。算起来,大概有十几个类似的新元素。

注意 尽管语义元素在HTML5的新功能里不怎么起眼,但它们的数量却不少。HTML5新增的大部分元素都是语义元素。

所有语义元素都有一个显著的特点:不真正做任何事。相对来说,<video>元素则囊括了在页面中充当视频播放器的全部能力。有读者可能会问了,既然它们不会改变网页的外观,那为什么还要使用这些新元素呢?

有如下几条理由。

  • 容易修改和维护。解读传统的网页比较困难。要想理解整体布局和不同区块的重要程度,必须得一遍一遍地看网页的样式表。但通过使用HTML5的语义元素,通过标记就可以传达出额外的结构化信息。这样,等你几个月后再回头修改网页,就不会像以前那么头疼了。当然,如果是其他人需要帮你改进页面,使用语义元素就显得更重要了。
  • 无障碍性。现代Web设计的一个重要主题,就是让任何人都能无障碍地访问网页。换句话说,要让使用屏幕阅读器和其他辅助工具的人都能在页面中自由导航。目前,开发无障碍工具的公司还在为兼容HTML5而紧张地工作。等他们开发完了,残疾人士就可以有更好的上网体验了。(仅举一个例子,有了<nav>元素,屏幕阅读器就能够迅速返回导航区,进而找到网站的链接。)
  • 搜索引擎优化。像谷歌这样的搜索引擎,会使用强大的搜索机器人(search bot),这些搜索机器人自动在Web中爬行并获取每一个网页。然后扫描网页内容并将它们索引到搜索数据库中。如果谷歌能够更好地理解你的站点,那搜索者的查询就会越容易与你的内容匹配,因而你的网站列在搜索结果中的可能性也就越大。搜索机器人已经在检查一些HTML5的语义元素了,这样可以收集到它们索引的页面的更多信息。
  • 未来的功能。新浏览器和Web编辑工具一定会以这样或那样的方式利用语义元素。比如,浏览器可以提供一个页面的内容纲要,以方便访客跳转到页面中适当的区块,就像Microsoft Word 2010中的导航窗格。类似地,网页设计工具也可能会包含一些方便你构建或编辑导航菜单的功能,而方法就是组织你放在<nav>区块中的内容。

最关键的问题在于,如果你正确地使用了语义元素,就能够创建更加清晰的页面结构,就能够适应未来的浏览器和Web设计工具的发展趋势。而如果你还是抱着原来写HTML标记的老习惯不放,那就要跟未来擦肩而过了。

改造传统的HTML页面

要了解和熟悉新的语义元素(包括学习如何使用它们来构造页面),最好的方式莫过于拿一个经典的HTML文档作例子,然后把HTML5的一些新鲜营养充实进去。图1是我们要改造的第一个页面。这个页面很简单,只包含一篇文章,当然对于其他内容(如博客、产品说明或简短的新闻报道)也完全没有问题。

提示 访问www.prosetech.com/html5,可以查看或下载图1中的示例页面以及本章所有的示例页面。如果你想从头开始做,那就选择ApocalypsePage_Original.html,如果想直接查看使用HTML5改造之后的结果,请选择ApocalypsePage_Revised.html。

构造页面的老办法

要生成图1所示的页面,有很多种构造方法。让人高兴的是,这个示例页面使用的是HTML最佳实践,因此没有任何通过标记来进行格式化的痕迹。没有粗体或斜体元素,没有嵌入的样式,当然更没有土得掉渣的<font>之类的东西。总之,这是一个格式非常规范的页面,所有样式均来自外部样式表。

以下是从页面中摘出的一段标记,代码中加粗的地方表明应用了样式:

<div class="Header">
  <h1>How the World Could End</h1>
  <p class="Teaser">Scenarios that spell the end of life as we know</p>
  <p class="Byline">by Ray N. Carnation</p>
</div>

<div class="Content">
  <p><span class="LeadIn">Right now</span>, you're probably ...</p>
  <p>...</p>

  <h2>Mayan Doomsday</h2>
  <p>Skeptics suggest ...</p>
  ...
</div>

<div class="Footer">
  <p class="Disclaimer">These apocalyptic predictions ...</p>
  <p>
    <a href="AboutUs.html">About Us</a>
    ...
  </p>
  <p>Copyright © 2011</p>
</div>

在一个(像这个一样的)编写规范的传统HTML页面中,通过使用<div>和<span>元素,已经把大部分工作移交给了样式表。通过<span>可以为处在其他元素中的少量文本添加样式,而通过<div>不仅可以为整个内容区块添加样式,还可以构建起整个页面的结构(见图2)。

这个例子中的样式表比较简单。整个页面的最大宽度设置为800像素,避免文本在宽屏显示器上显示得过长。页眉位于一个带蓝色边框的盒子中,内容区的两侧都添加了内边距,而页脚在整个页面底部居中。

因为使用了<div>元素,所以添加样式很容易。比如,下面就是为页眉及其中内容添加样式的规则。

/*为<div>添加样式,使其具有页眉的外观(蓝色带边框)*/
.Header {
  background-color: #7695FE;
  border: thin #336699 solid;
  padding: 10px;
  margin: 10px;
  text-align: center;
}

/*为页眉中的<h1>添加样式(这是文章的标题)*/
.Header h1 {
  margin: 0px;
  color: white;
  font-size: xx-large;
}

/*为页眉中的子标题添加样式*/
.Header .Teaser {
  margin: 0px;
  font-weight: bold;
}

/*为页眉中的署名行添加样式*/
.Header .Byline {
  font-style: italic;
  font-size: small;
  margin: 0px;
}

使用HTML5构造页面

<div>是当今Web设计的必备元素,它是一个直观、多用途的容器,可以通过它为页面中的任何区块应用样式。但<div>的问题在于,它本身不反映与页面相关的任何信息。在你(或浏览器、设计工具、屏幕阅读器、搜索机器人)遇到一个<div>元素时,你知道它是页面中独立的一个区块,可是你不知道那个区块的意图。

要通过HTML5改进这种情况,可以把<div>替换成更具有描述性的语义元素。这些语义元素的行为与<div>元素类似:它们仅包含一组标记,除此之外没有其他作用,可以将它作为“格式挂钩”来为页面应用样式。不过,除此之外,它们还会为页面添加一点语义。

下面的代码是在图1所示页面基础进行了简单修改之后的结果,删除了两个<div>元素,但添加了两个HTML5的语义元素:<header>和<footer>

<header class="Header">
  <h1>How the World Could End</h1>
  <p class="Teaser">Scenarios that spell the end of life as we know</p>
  <p class="Byline">by Ray N. Carnation</p>
</header>

<div class="Content">
  <p><span class="LeadIn">Right now</span>, you're probably ...</p>
  <p>...</p>

  <h2>Mayan Doomsday</h2>
  <p>Skeptics suggest ...</p>
  ...
</div>

<footer class="Footer">
  <p class="Disclaimer">These apocalyptic predictions ...</p>
  <p>
    <a href="AboutUs.html">About Us</a>
    ...
  </p>
  <p>Copyright © 2011</p>
</footer>

在这里,<header>和<footer>元素替代了原来的<div>元素。如果你在修改一个大型网站,可以考虑用HTML5中相应的语义元素来包装已有的<div>元素。

可能你已经注意到了,这里的<header>和<footer>元素仍然使用了类名。这样做的目的就是不用立即修改样式表。可不管怎么说,这里的类名还是有点多余。所以,最终结果就是把它们都删掉:

<header>
  <h1>How the World Could End</h1>
  <p class="Teaser">Scenarios that spell the end of life as we know</p>
  <p class="Byline">by Ray N. Carnation</p>
</header>

因为页面中只有一个<header>元素,所以可以直接通过元素名选择它。下面是修改之后的为<header>及其包含的所有元素应用样式的规则:

/*为<header>添加样式,使其具有页眉的外观(蓝色带边框)*/
header {
  ...
}

/*为<header>中的<h1>添加样式(这是文章的标题)*/
header h1 {
  ...
}

/*为<header>中的子标题添加样式*/
header .Teaser {
  ...
}

/*为<header>中的署名行添加样式*/
header .Byline {
  ...
}

这两种应用样式的方式都会得到相同的结果。正如HTML5中的很多设计问题一样,可能需要充分地讨论,但到底该怎么做,没有硬性规定。

此时,也许你会问:为什么内容部分的<div>元素还保留着呢?这样没有问题,因为HTML5页面经常会混合各种语义元素和更通用的<div>容器。HTML5没有“content”元素,所以仍然可以使用<div>元素。

最后,还有一个元素有必要用在示例页面中。那就是HTML5的<article>元素,这个元素表示一个完整的、自成一体的内容块,比如博客文章或新闻报道。<article>元素应该包含所有相关的内容,包括标题、作者署名以及正文。添加了<article>元素之后的页面结构就变成如下所示:

<article>
  <header>
    <h1>How the World Could End</h1>
    ...
  </header>

  <div class="Content">
    <p><span class="LeadIn">Right now</span>, you're probably ...</p>
    <p>...</p>
    <h2>Mayan Doomsday</h2>
    <p>Skeptics suggest ...</p>
    ...
  </div>
</article>

<footer>
  <p class="Disclaimer">These apocalyptic predictions ...</p>
  ...
</footer>

图3是最终的页面结构示意图

尽管此时的页面在浏览器中看起来还是一样的,但后台已经潜伏了一些额外的信息。此时,如果正好一个搜索机器人造访你的网站,停留在这个页面上,那它就能迅速找到页面的内容(通过<article>元素)以及该内容的标题(通过<header>元素)。至于页脚,它就不会太在意了。

<hgroup>标注副标题

在前面的例子中,我们已经让<header>物尽其用了。可是,HTML5实际上新增了两个与标题相关的元素:一个是<header>,另一个是<hgroup>。以下是如何使用这两个元素的规范做法:

首先,如果有一个普通的标题,它本身不包含任何特殊的内容,那使用一个带编号的标题元素(即<h1>、<h2>、<h3>等)就可以了:

<h1>How the World Could End</h1>

如果除了主标题,还有一个副标题,那可以把这两个标题包装在一个<hgroup>元素中。但是,这里面除了编号的标题元素(即<h1>、<h2>、<h3>等),其他任何元素也不要放:

<header>
<hgroup>
  <h1>How the World Could End</h1>
   <h2>Scenarios that spell the end of life as we know</h2>
</hgroup>
  <p class="Byline">by Ray N. Carnation</p>
</header>

当然,这也是在前面例子的基础上修改的结果,只不过把文章的副标题放在了<h2>元素而非<p>元素中。

<h2>替换<p>之后,标记看起来有点不太对劲儿。从结构上讲,好像接下来的内容都属于以二级标题<h2>开头的小节了,这样不太合理。毕竟,把一篇文章的内容全都放在一个小节里有点说不过去。。

好在,有<hgroup>元素,这个问题就迎刃而解了。从结构上讲,它只关注顶级标题(也就是这里的<h1>)。其他标题也会显示在浏览器中,但不会被列入文档纲要。这个结果是非常合理的,因为这里的标题是文章的副标题,并不表示小节的开始。

<figure>添加插图

很多页面中都包含图片。但是,插图(figure)与图片的概念还不完全一样。HTML5规范建议我们把插图想象成一本书中的附图;换句话说,插图虽然独立于文本,但文本中会提到它。

一般来说,插图应该是浮动的;换句话说,应该把它放在相关文本旁边的一个比较近便的位置上(不要把它们锁定在特定的词或元素旁边)。而且,插图通常还会有与之相伴的浮动图题。

下面是给这篇启示录般的文章添加插图的HTML标记。(其中也包含正好在它前面和后面的两个段落,这样你就能知道插图在标记中的确切位置了。)

<p><span class="LeadIn">Right now</span>, you're probably ...</p>

<div class="FloatFigure">
  <img src="human_skull.jpg" alt="Human skull">
  <p>Will you be the last person standing if one of these apocalyptic
   scenarios plays out?</p>
</div>

<p>But don't get too smug ...</p>

光有这些标记还不行,必须还得有相应的样式表规则,才能把插图定位到适当的位置(同时添加外边距、控制图题文本的格式,当然你也可以自己给它添加一个边框)。下面就是给出的样式规则:

/*为插图应用样式*/
.FloatFigure {
  float: left;
  margin-left: 0px;
  margin-top: 0px;
  margin-right: 20px;
  margin-bottom: 0px;
}

/*为图题应用样式*/
.FloatFigure p {
  max-width: 200px;
  font-size: small;
  font-style: italic;
  margin-bottom: 5px;
}

图4展示了目前这个示例页面的外观。

如果你以前也是这样为内容添加插图的,那在听说HTML5专门为你量身打造了一个新的语义元素,一定会高兴得合不拢嘴。没错,在这里可以不再用那个乏味的<div>了,因为现在有了一个专门的<figure>元素。那么图题呢?图题可以放在<figure>中的<figcaption>元素里:

<figure class="FloatFigure">
   <img src="human_skull.jpg" alt="Human skull">
   <figcaption>Will you be the last person standing if one of these
   apocalyptic scenarios plays out?</figcaption>
</figure>

当然,给插图和图题应用什么样式,把它们放在什么位置上,还是由你说了算。(对这个例子来说,你得修改样式规则的选择符,才能重新选中图题文本。现在使用的是.FloatFigure p,而修改之后应该是.FloatFigure figcaption。)

打开浏览器看一下,插图还是那样。但不同的是标注插图的标记现在的含义已经非常明确了。(顺便提个醒,<figcaption>元素不是只能包含文本——任何HTML元素都可以,比如链接、小图标等。)

最后,有必要再说一件事。因为图题中经常就包含了对图片的完整说明,所以alt文本就显得有点多余了。这种情况下,可以把<img>元素中的alt属性删除:

<figure class="FloatFigure">
   <img src="human_skull.jpg">
   <figcaption>A human skull lies on the sand</figcaption>
</figure>

这里要小心的是,不能把alt文本设成空字符串。因为这就意味着你的图片纯粹是装饰用的,屏幕阅读器会忽略不读。

<aside>添加附注

新的<aside>元素表示与它周围的文本没有密切关系的内容。这就是说,你可以像在印刷品中使用附注栏一样使用<aside>元素,可以通过它介绍另一个相关的话题,或者对主文档中提出的某个观点进行解释。另外,也可以用<aside>来盛放广告、相关内容链接,甚至如图5所示的醒目引文(pull quote)。

当然,使用熟悉的<div>元素也可以创造这种效果,但用<aside>元素包装同样的内容,可以让标记更富有意义:

<p>... (in a suitably robotic voice) "Who's your daddy now?"</p>

<aside class="PullQuote">
  <img src="quotes_start.png" alt="Quote">
  We don't know how the universe started, so we can't be sure it won't
  just end, maybe today.
  <img src="quotes_end.png" alt="End quote">
</aside>

<h2>Unexplained Singularity</h2>

这一次,样式表把醒目引文浮动到了右边。为满足你的好奇心,下面给出了相应的样式:

.PullQuote {
  float: right;
  max-width: 300px;
  border-top: thin black solid;
  border-bottom: thick black solid;
  font-size: 30px;
  line-height: 130%;
  font-style: italic;
  padding-top: 5px;
  padding-bottom: 5px;
  margin-left: 15px;
  margin-bottom: 10px;
}

.PullQuote img {
  vertical-align: bottom;
} 

浏览器对语义元素的支持情况

到目前为止,我们做练习做得还是很开心的。不过,要是你用一个比较早的浏览器打开这个页面,结果恐怕就没有那么令人满意了。在讨论这些内容之前,有必要先了解一下哪些浏览器支持这些简单的语义元素。表1列出了支持的浏览器。

提示 IE Firefox Chrome Safari Opera iOS Safari Android
最低版本 9 4 8 5 11.1 4 2.1

幸运的是,语义元素还是一个比较容易弥补的功能。毕竟,语义元素本身什么也不做,要支持它们,只要让浏览器把它们当做普通的<div>元素就行了。为了做到这一点,需要解决两个问题。

语义元素是怎么来的

在发明HTML5之前,其发明者花了很长时间研究已有的网页。他们不是光浏览自己喜欢看的站点,还研读了谷歌对十亿个网页的统计信息。(如果你对这个出色的研究感兴趣,可以看看这里:http://code.google.com/webstats,最好别用IE看,因为Internet Explorer不会显示那些漂亮的图表。)

谷歌公布的这个调查分析并列出了Web作者在自己网页中使用的类名。谷歌的目的是想告诉大家,你们使用的类名可能与匹配的元素的用途相悖,从而为大家构造网页提供有价值的参考。比如,要是所有人都会给一个<div>元素指定名为header的类名,那么就可以推断出大家都把页眉内容放在网页的顶部。

谷歌发现的最重要的一个现象,就是大量的网页根本不使用类名(甚至连样式表都没有)。然后,他们汇编了一组最常用的类名,包括footer、header、title、menu、nav,分别对应着HTML5中的<footer>、<header>、<nav>等新语义元素。另外一些由其他人建议但尚未创造出来的语义元素有search和copyright等。

换句话说,Web页面拥有某种共性的东西,比如页面都有页眉、页脚、侧边栏和导航菜单。只不过大家在区分这些构造时采用的方式多多少少有点不一致。基于这个认识,从人们普遍的做法中提取出相应的语义,据以为HTML语言添加一些新元素,也就成了自然而然的事了。这就是HTML5中语义元素的来历。

首先,需要克服浏览器天生把不认识的元素当成内联(inline)元素的习惯。大多数HTML5语义元素(包括已经介绍的这些,但除<time>之外)都是块级元素,也就是需要在单独一行上来呈现它们,同时在它们与前后元素之间各添加一些空间。

不认识HTML5语义元素的浏览器不知道应该把它们显示为块级元素,所以很可能会把它们都挤到一起。为解决这个问题,只要在样式表中添加一条“超级规则”即可。下面就是一条为9个HTML5元素应用块级显示格式的规则:

article, aside, figure, figcaption, footer, header, hgroup, nav, section,
summary {
  display: block;
}

这条规则对于能够识别HTML5元素的浏览器没有作用,因为它们的display属性已经被默认设成了block。而且这条规则也不影响我们已经为这些元素应用的样式。那些样式照样可以添加到它们身上。

对于大多数浏览器而言,第一种技术可以解决问题。但这里的“大多数”并不包括Internet Explorer 8及更早的版本。换句话说,对于较早版本的IE,还要面临一个挑战:它们会拒绝给无法识别的元素应用样式。好在,有一个变通方案:通过JavaScript创建新元素,就可以骗过IE,让它识别外来元素。比如,下面的脚本可以让IE识别并为<header>元素应用样式:

<script>
  document.createElement('header')
</script>

实际上,你不用自己亲手写这些代码,因为已经有人为你写好了,只要拿过来用就可以了(参见http://tinyurl.com/nlcjxm)。要使用这个脚本,只要在页面的<head>区块中引用它即可,就像这样:

<head>
  <title>...</title>
  <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
  ...
<head>

这行代码会从html5shim.googlecode.com这个Web服务器上取得脚本,然后在浏览器处理页面其余部分之前运行。这个脚本很短而且十分有效——它就是使用前面描述的JavaScript代码创建了所有的新HTML5元素。然后,你就可以使用样式表为它们应用样式了。把前面的“超级规则”放到样式表中,新元素就能正确地显示为块元素了。现在,剩下的事儿就是使用这些元素,并为它们应用你自己的样式。

对了,刚才忘说了,前面的html5.js脚本应该是有条件执行的——只在你使用旧版本Internet Explorer的情况下才会执行。为了避免不必要地加载JavaScript文件,可以像下面这样把引用脚本的代码放在IE的条件注释中:

<!--[if lt IE 9]>
  <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->

这样,其他浏览器(IE9及更高版本)就会忽略这行脚本,为你的页面节省数毫秒的加载时间。

提示 要解决为语义元素应用样式的问题,还有一个方案:使用Modernizr。Modernizr会自动替你解决上述问题,也不用使用html5.js或者样式规则。因此,如果你已经在用Modernizr检测功能了,那么要考虑的就只有怎么使用语义元素了。

使用语义元素设计站点

在一个简单、类似文档的页面中应用语义元素相对容易。如果是把它们应用到整个站点也没有任何困难,但必须面对一系列新问题。因为HTML5还是一块未被开垦的处女地,很少有约定俗成的惯例(但却有一大堆合情合理的争议)。这样说吧,假设你准备从两种标记方案中选择一种,HTML5标准会说它们都是完全可以接受的,至于哪个方案最适合你的内容,你自己说了算。

图6展示了我们接下来将要设计的一个更有创造性的作品。

理解<header>

对于<header>元素来说,有两种使用方式,但差别并不大。一种是用它标注内容的标题,另一种是用它标注网页的页眉。有时候,这两种用途是重叠的(比如图1中那个单页文章的例子)。但有时候,你的网页里不仅要用<header>标注页眉,还要用它去标注很多内容的标题。图6所示的例子就是这种情况。

但有时候到底该不该用<header>并不十分明确,因为要标注的内容区块的角色变化会影响最终的决策。如果你处理的是内容,那除非必要,一般不必使用<header>。只有在内容标题还附带了其他信息的情况下,才有必要考虑<header>。如果你的内容就只有一个标题,那就用一个<h1>足够了。类似地,如果除了主标题,还有一个或几个副标题,那顶多也就是把<hgroup>用上。假如除此之外还有其他信息,那才有必要用<header>把主副标题以及其他信息包装起来。不过,在为网站创建页眉的时候,人们多数会直接考虑<header>元素,即便这个页眉就是一个CSS控制的长盒子,里面啥都没有。毕竟页眉是网站的一个核心组件,谁知道哪天你要往里面塞点什么东西呢!

结论如下:网页中可以包含多个<header>元素(通常也应该如此),即使相应的区块在页面中的角色不一样。

图6所示的启示录网站新增了一个站点的页眉。这个页眉的内容是一张横幅图片,图片中的文本也是由图片编辑器生成的。以下就是这个站点使用的<header>元素:

<header class="SiteHeader">
  <img src="site_logo.png" alt="Apocalypse Today">
  <h1 style="display:none">Apocalypse Today</h1>
</header>

在此,我们注意到页眉中还包含一个我们在页面中看不到的<h1>元素,其中的内容与图片中的文本内容相同。而一条内联样式隐藏了这个标题。

这个例子提出了一个明显的问题——为什么要添加一个你看不见的标题?原因其实不止一个。首先,<header>元素中都应该包含某个级别的标题,这样做仅仅是为了遵守HTML5的规定。其次,这样设计可以让使用屏幕阅读器的人能够无障碍地阅读,因为他们经常会从一个标题跳到另一个标题,而不会关注标题之间的内容。最后,这样就为页面建立了标题结构,而页面其他部分的标题都要依序选用。如果我们说,在站点的页眉中使用了<h1>元素后,你就应该给页面中其他的区块(如“Articles”和“About Us”)选用<h2>元素作标题,你可能觉得有点怪。要了解为什么这样设计,请参考下面的附注栏“站点的标题结构”。

<nav>标注导航链接

这个启示录网站中最有意思的新功能就是左侧的侧边栏,其中包含网站的导航、其他信息和一张图片广告。(一般来说,广告位都是放一段JavaScript脚本,从类似Google AdSense等服务随机地提取广告。但我们这个例子就硬编码了一张图片,就算是一种替代吧。)

在传统的HTML网站中,你可能会把整个侧边栏都放到一个<div>中。而在HTML5时代,则应该主要使用两个针对性更强的元素:<aside><nav>

要说<aside>元素,倒是跟<header>元素有点像,哪里像呢?<aside>的含义也有一点细微的发散。可以用它来标注一段与正文无关的内容,也可以用它表示页面中一个完全独立的区块——作为页面主要内容的陪衬。

<nav>元素则用于包装一组链接。这些链接可以指向当前页面中的主题,也可以指向网站中的其他页面。多数页面中都会包含多个<nav>区块。但并不是所有链接都需要<nav>区块——相反,<nav>通常只用于页面中最大最主要的导航区。例如,对于一组文章的链接(像图6那样的),绝对需要一个<nav>区块。可是,如果只是放在页面底部几个许可或联系信息的链接,那大可不必麻烦<nav>

明白了这两个元素的用途,接下来该付诸实践了。首先,再看一看图6中的侧边栏。然后,在一张纸上画一画,看你打算怎么用标记体现其中内容的结构。最后,再接着往下看,一块来找一个最佳方案。

事实上,如图7所示,至少有两个比较合理的方式来构造侧边栏。

左:可以把整个侧边栏想象成一个导航区,在其中填入一些内容。这样,整个侧边栏可以放在一个<nav>中,其他内容可以使用<aside>(因为其中的内容与侧边栏的主要内容——链接无关)。
右:或者,可以把整个侧边栏想象成一个独立的多用途的网页区块。这样,侧边栏就是一个<aside>,而其中有关导航的内容放在<nav>里面

这个启示录站点使用的是第二种方案(即图7中右侧的结构)。选择该方案主要是因为这里的侧边栏有多种用途,而没有哪一种用途是主要用途。不过,要是这里的导航又长又复杂(比如都用上了可折叠的菜单形式),只是后面跟着一小段内容,那第一种方案就更合适一些。

以下就是构成侧边栏的标记,包含三个区块:

<aside class="NavSidebar">
  <nav>
    <h2>Articles</h2>
    <ul>
      <li><a href="...">How The World Could End</a></li>
      <li><a href="...">Would Aliens Enslave or Eradicate Us?</a></li>
      ...
    </ul>
  </nav>

  <section>
    <h2>About Us</h2>
    <p>Apocalypse Today is a world leader in conspiracy theories ..."
    </p>
  </section>

  <div>
    <img src="ad.jpg" alt="Luckies cigarette ad: it's toasted">
  </div>
</aside>

看完这些代码,应该注意到如下关键点。

  • 标题(Articles和About Us)使用的是二级标题。这样,它们就自然位于网站的一级标题之下,从而方便屏幕阅读器无障碍地阅读标题。
  • 链接<ul>和<li>元素组成的无序列表来标记。网站设计师普遍认为,处理一组链接的最佳方式,也是最无障碍的方式,就是使用列表。不过,你可能得通过样式表删除列表项默认的缩进(这个例子已经这样做了)和项目符号(本例没有项目符号)。
  • “About Us”包含在一个<section>元素中。这是因为没有合适的语义元素。<section>当然要比<div>更具体一点,它适合任何以标题开头的内容区块。假如有一个更具体的元素(例如,假设有一个<about>元素),那么这里就不会用<section>,可惜没有。
  • 图片广告放在一个<div>里。如前所述,<section>元素只适合带标题的内容,而这里的图片区块没有标题。(而如果真有的话,比如“A Word from Our Sponsors”,那就该用<section>元素了。)从技术角度看,根本没有必要把图片还放在其他元素中。但有了<div>,区块之间的关系就更明确了,这样更容易分别为不同的区块应用样式,或者在必要时通过JavaScript分别操作它们。

实际上,还有一些细节,这个侧边栏里没有,但可能其他侧边栏里会有。比如,复杂的侧边栏可能会以<header>和<footer>作为开头和结尾,也有可能包含多个<nav>区块——存档文章链接一个、新闻报道链接一个、友情链接或相关站点链接一个,等等。有兴趣的话,读者可以自己找找一些有代表性的博客,其中的侧边栏往往包含很多区块,其中不少都是导航用的。

这里为<aside>标注的侧边栏应用样式的规则,与为传统的<div>标注的侧边栏应用样式的规则一样。它们都会把侧边栏摆放到正确的位置上,使用绝对定位,设置某些格式上的细节,如内边距、背景,等等:

aside.NavSidebar
{
  position: absolute;
  top: 179px;
  left: 0px;
  padding: 5px 15px 0px 15px;
  width: 203px;
  min-height: 1500px;
  background-color:#eee;
  font-size: small;
}

这条规则后面是一些上下文样式表规则,分别为侧边栏中的<h2>、<ul>、<li>以及<img>元素应用样式。

注意 我们已经介绍了,<nav>通常会单独出现,有时候也会出现在<aside>中。其实,还有一个地方也经常可以看到它的身影:网页顶部的<header>元素中。

理解了这个侧边栏是如何构造的,也就容易理解它与整个页面布局的关系了,如图8所示。

理解<footer>

HTML5与内容丰富的“胖”<header>可谓天生一对。在<header>中不仅可以放副标题和作者署名,还可以添加图片、导航区块(使用<nav>元素),以及任何有必要放在页面顶部的内容。

奇怪的是,HTML5对<footer>元素可就不那么有人情味了。HTML5规定,只能在<footer>元素中放一些网站版权信息、作品来源、法律限制及链接之类的信息。不能在<footer>里面放太多链接、重要的内容或无关的内容,如广告、社交媒体按钮以及网站部件等。

这就提出了一个问题:如果你的网站需要一个“胖”<footer>怎么办?毕竟,“胖”页脚目前非常流行(见图9中的例子)。这些“胖”页脚经常会用到如下所示的一些花哨的技术。

这个荒唐的“胖”页脚中包含不少多余的内容,比如一个奖项图片和一些社交媒体按钮。它使用了固定定位使自己一直显示在浏览器窗口底部,就像一个工具条。好在这个页脚有一个地方可以弥补它的缺点,那就是右上角的关闭按钮,单击该按钮就能让这个页脚从视野中消失

  • 固定定位,这样就可以让页脚始终固定在浏览器窗口底部,无论访客如何滚动都无所谓(如图9中的例子所示)。
  • 关闭按钮,这样用户在看完页脚内容后,单击它们就可以腾出页面空间(如图9中的例子所示)。为实现这个功能,要使用一点JavaScript代码(与前一节附注栏中使用的代码相似),以便隐藏包含页脚的元素。
  • 部分透明的背景,这样就可以透过页脚看到内容。如果页脚正在宣布即时新闻或重要的免责声明,部分透明的背景很合适,通常与关闭按钮联用。
  • 动画,在视图中弹出,或者滑入视图(例如,可以看看在http://www.nytimes.com上阅读到一篇文章最后时弹出的相关文章提示框)。

如果你的站点中包含这种页脚,就要作出选择。比较简单的办法是无视规定。这个办法并没有听起来那么可怕,因为其他网站的开发人员也在犯同样的错误。而随着时间推移,官方的规定也可能会放开,允许用<footer>包含奇特的页脚。可是,假如你现在不想违反标准的规定,那就得调整一下标记。好在调整标记不难。

调整标记的关键在于从多余的内容中提取出标准的页脚来。在浏览器中,这些内容看起来还是一个页脚,但在标记中,其他内容都不包含在<footer>元素中。例如,以下就是图9中“胖”页脚的实际结构:

<div id="FatFooter">
  <!--“胖”页脚的内容 -->
  <img onclick="CloseBox()" src="close_icon.png" class="CloseButton">
  ...

  <footer>
    <!-- 标准页脚的内容 -->
    <p>The views expressed on this site do not ... </p>
  </footer>
</div>

最外围的<div>没有特殊含义,它只是负责把多余的内容和标准的页脚内容包装起来。同样,可以给它应用一些样式表规则,以便将其锁定在合适的位置上:

#FatFooter {
  position: fixed;
  bottom: 0px;
  height: 145px;
  width: 100%;
  background: #ECD672;
  border-top: thin solid black;
 font-size: small;
}

注意 在这个例子中,样式表规则是通过ID应用样式的(使用#FatFooter选择符),并没有使用类名(如.FatFooter选择符)。这是因为“胖”页脚本身已经有了唯一的ID,目的是为了方便JavaScript代码在用户单击关闭按钮时可以找到并隐藏它。这种情况下,在样式表中使用唯一的ID要比另外添加一个类名更可取。

当然,也可以把页脚中的其余内容放在一个<aside>元素中,从而清楚地表明其中的内容属于一个独立的区块,与页面中的其他内容无关。相应的标记结构类似如下所示:

<div id="FatFooter">
  <aside>
    <!--“胖”页脚的内容 -->
    <img onclick="CloseBox()" src="close_icon.png" class="CloseButton">
    ...
  </aside>
  <footer>
    <!-- 标准页脚的内容 -->
    <p>The views expressed on this site do not ... </p>
  </footer>
</div>

这里最重要的一点是没有把<footer>放到<aside>元素中。因为<footer>并不属于<aside>,而是整个网站的一部分。类似地,如果有一个<footer>属于某些内容,那么就应该将这个<footer>放在包含相应内容的元素中。

注意 正确使用HTML5语义元素的规则和指导方针还在变化。在HTML社区中,有关如何在大型、复杂站点中正确使用标记的话题,常常会引起激烈的争论。在此,我给大家一个建议:如果某个元素看起来不适合标注你的内容,那就不要用。当然,你也可以上网去讨论,很多超聪明的HTML大师会为你现身说法。(最好的一个去处就是http://html5doctor.com,在该网站大多数文章的评论中,都可以看到正在争论中的话题。)

理解区块

如前所述,区块元素<section>是应该最后考虑的语义元素。如果有一个带标题的内容块,而其他语义元素都不合适,那么选择<section>通常比选择<div>更好一些。

那么通常应该在<section>元素中放什么呢?这跟你的看法有关,它可能是一个能够适合各种需求的灵活的工具,也可能是一个松松垮垮没有明确身份的怪物。之所以会有这么大的区别,主要是因为<section>在网页中可以扮演很多不同的角色。可以放在<section>中的内容有以下几种。

  • 与页面主体内容并列显示的小内容块,例如我们启示录网站中的About Us段落。
  • 独立性内容,但却不能用文章(<article>)来描述,比如客户的购物记录或产品清单。
  • 分组内容——例如,新闻站点中的一组文章。
  • 比较长的文档中的一部分。比如,在启示录网站的文章中,可以用它把每种世界末日的情形标注为一个独立的区块。有时候,这样使用区块是为了保证文档能有一个正确的纲要,而这正是下一节我们要介绍的内容。

前面列出的最后两项可能会令你觉得很不可思议。很多Web开发人员会觉得用一个元素既可以标注一篇文章中的一个片段,又可以标注整个一组文章,这伸缩性似乎有点大了。有人认为HTML5至少应该用两个不同的元素来对应这两种情况。但HTML5的创造者希望一方面保持简单(限制新元素的数量),另一方面也让新元素尽可能灵活且实用。

语义元素总结

元素 说明
<article> 表示一篇任何形式的文章,即类似新闻报道、论坛帖子或博客文章(不包括评论或作者简介)等能够独立的内容区块
<aside> 表示独立于周围内容的一个完整的内容块。例如,可以用<aside> 创建一个附注栏,其中包含与主文章相关的内容或链接
<figure><figcaption> 表示一幅插图。其中<figcaption>元素标注图题(插图的标题),而<figure>元素标注<figcaption>和插入图片的<img> 元素。目标是反映图片与图题之间是关联的
<footer> 表示页面底部的页脚 。通常是很小的一块内容,包括小字号的版权声明、简单的链接(比如About Us、Get Support等)
<header> 表示增强型的标题,可以包含HTML标题和其他内容。其他内容可以是标志、作者署名或一组指向后面内容的导航链接
<hgroup> 表示增强型的标题,分组两个或多个标题元素,不包含其他内容。其主要目的是把标题和副标题联系到一起
<nav> 表示页面中重要的一组链接。其中的链接可以指向当前页面的主题,也可以指向网站的其他页面。实际上,一个页面中包含多个<nav> 也很正常
<section> 表示文档中的一个区块,或者表示一组文档。<section>是一个通用容器,只有一条规则:其中的内容必须开始于一个标题。应该在其他语义元素(如<article><aside>)不适用的情况下再选用<section>

参考文档