注意:下面描述的HTML5大纲算法在用户代理中还没有实现,因此,使用标题语义的用户暴露在HTML4的文档结构下。HTML5对问题的描述还仅仅是理论上的。
HTML5新增了几个新元素使得开发者可以用标准语义去描述web文档的结构。本文描述了这些元素并说明如何使用这些元素去为任何文档定义纲要。
HTML4的文档结构
文档结构,即,<body>标记之间内容的语义结构,对呈现页面给用户是重要的。HTML4用文档中章节和子章节的概念去描述文档结构。一个章节由一个包含着标题元素(h1-h6)的div元素表示。这些html划分元素(HTML Dividing Elements)和标题元素(HTML Heading Elements)形成了文档的结构和纲要。
所以下面的片段
形成了如下的大纲:
1. Forest elephants 1.1 Habitat
HTML div元素( <div>
elements)并不强制性地定义一个章节。一个HTML 标题元素( HTML Heading Element)的出现就足以意味着新的章节. 因此,
<h1>Forest elephants</h1> <p>In this section, we discuss the lesser known forest elephants. ...this section continues... <h2>Habitat</h2> <p>Forest elephants do not live in trees but among them. ...this subsection continues... <h2>Diet</h2> <h1>Mongolian gerbils</h1>
形成如下的大纲:
1. Forest elephants 1.1 Habitat 1.2 Diet 2. Mongolian gerbils
HTML5解决的问题
HTML 4 的文档结构定义和其隐含的大纲算法非常粗糙而且造成了很多问题:
- 定义语义性章节的
<div>
元素的用法,如果没有为class属性赋以特殊的值,使生成自动生成大纲的算法变得不可能 ("一个div元素<div>
是不是大纲的一部分, 定义的是章节还是子章节?" 或者 "该div元素<div>
是仅仅为了样式化?")。换句话说, HTML4规范在章节的定义和章节的范围都不精确。 自动生成大纲是重要的,尤其是在倾向于通过根据文档大纲内容去展示内容的辅助技术( assistive technology)。 HTML5 在自动生成大纲算法的过程中去掉了div元素(<div>
),并新增了一个元素,section元素(<section>
)。 - 合并多个文档是困难的:主文档中包含子文档意味着改变HTML标题元素的级别,以使得文档大纲能够保持下来。 这个已经被HTML5的新的章节元素解决了,因为新引入的元素(
<article>
,<section>
,<nav>
和<aside>
) 总是距离其最近的祖先章节的子章节, 与子文档章节内部的标题没有关系. - HTML4中,所有的章节都是文档大纲中的一部分。但是文档并不总是这样。文档可以包含那些不是大纲的特殊章节, 但是与文档有关的, 就像广告块和解释区域。 HTML5 引入aside元素
<aside>
使得这样的节点不会插入到主纲要中。 - 另外, 因为在 HTML4中任何的部分都是文档大纲的一部分, 没有办法产生与网站相关而不是与文档相关的节段,比如logos,menus,目录或版权信息和法律声明。为了这个目的, HTML5 引入了三个特殊的节段 元素: 包含链接集合的nav元素
<nav>
, 例如目录, 包含网站相关信息的footer元素<footer>
和header元素<header>
。
更具有普遍意义的是HTML5使得章节和标题特性更精确。使得文档大纲变的可预测,浏览器使用后也可以提高用户体验。
HTML5的大纲算法
定义节段
<body>
元素中的所有内容都是节段中的一部分。节段在HTML5中是可以嵌套的。<body>
元素定义了主节段,基于主节段,可以显式或隐式定义各个子节段的划分。显式定义的节段是通过<body>
, <section>
, <article>
, <aside>
, <footer>
, <header>
和 <nav>
这些标记中的内容。
Example:
<section> <h1>Forest elephants</h1> <section> <h1>Introduction</h1> <p>In this section, we discuss the lesser known forest elephants.</p> </section> <section> <h1>Habitat</h1> <p>Forest elephants do not live in trees but among them.</p> </section> <aside> <p>advertising block</p> </aside> </section> <footer> <p>(c) 2010 The Example company</p> </footer>
这个HTML片段定义了两个顶级节段:
<section> <h1>Forest elephants</h1> <section> <h1>Introduction</h1> <p>In this section, we discuss the lesser known forest elephants.</p> </section> <section> <h1>Habitat</h1> <p>Forest elephants do not live in trees but among them.</p> </section> <aside> <p>advertising block</p> </aside> </section> <footer> <p>(c) 2010 The Example company</p> </footer>
第一个节段有三个子节段:
<section> <h1>Forest elephants</h1> <section> <h1>Introduction</h1> <p>In this section, we discuss the lesser known forest elephants.</p> </section> <section> <h1>Habitat</h1> <p>Forest elephants do not live in trees but among them.</p> </section> <aside> <p>advertising block</p> </aside> </section> <footer> <p>(c) 2010 The Example company</p> </footer>
上面的片段形成了如下的大纲:
1. Forest elephants 1.1 Introduction 1.2 Habitat 1.3 Section (aside)
在HTML5中定义标题
当 HTML 节段元素定义文档结构时,文档大纲也需要有用的标题。基本规则是简单的:第一个 HTML 标题元素(<h1>
, <h2>
, <h3>
, <h4>
, <h5>
, <h6>
之一)定义了当前节段的标题
标题元素通过在元素里的名字加上数字来分级标题元素,<h1>
元素有最高级别,<h6>
有最低级别。相关的级别只在节段中起作用;节段的结构定义了大纲,而不是节段的标题。例如,下面的代码:
<section> <h1>Forest elephants</h1> <p>In this section, we discuss the lesser known forest elephants. ...this section continues... <section> <h2>Habitat</h2> <p>Forest elephants do not live in trees but among them. ...this subsection continues... </section> </section> <section> <h3>Mongolian gerbils</h3> <p>In this section, we discuss the famous mongolian gerbils. ...this section continues... </section>
形成了下面的大纲:
1. Forest elephants 1.1 Habitat 2. Mongolian gerbils
注意标题元素的级别(例子中的第一个顶层节段的 <h1>
,子节段中的<h2>
和第二个顶层节段中的<h3>
)并不重要。(任何级别可以用作显示定义的节段的标题,虽然这种做法并不推荐。)
隐式分节
因为HTML5分节元素并不强制性定义大纲,为了与现有的占主导地位的HTML4保持兼容,有个方式来定义节段而不需要分节元素。这种方式就是隐式分节。
HTML标题元素 (<h1>
到 <h6>
) 定义了一个新的,隐式的节段,当其不是父节段第一个标题时。这种隐式放置节段的方式通过在父节点中与之前标题的相对级别来定义。如果比之前的标题级别更低,那么在节段里开始新的隐式子节段。如代码所示:
<section> <h1>Forest elephants</h1> <p>In this section, we discuss the lesser known forest elephants. ...this section continues... <h3 class="implicit subsection">Habitat</h3> <p>Forest elephants do not live in trees but among them. ...this subsection continues... </section>
形成如下的大纲:
1. Forest elephants 1.1 Habitat (implicitly defined by the h3 element)
如果与前面标题的级别相同,那么闭合前面的节段(可能是显式标记的节段!)并开始新的同一级别的隐式节段:
<section> <h1>Forest elephants</h1> <p>In this section, we discuss the lesser known forest elephants. ...this section continues... <h1 class="implicit section">Mongolian gerbils</h1> <p>Mongolian gerbils are cute little mammals. ...this section continues... </section>
形成如下的大纲:
1. Forest elephants 2. Mongolian gerbils (implicitly defined by the h1 element, which closed the previous section at the same time)
如果比之前标题的级别更高,那么关闭之前的节段并开始新的这个更高级别的隐式节段:
<body> <h1>Mammals</h1> <h2>Whales</h2> <p>In this section, we discuss the swimming whales. ...this section continues... <section> <h3>Forest elephants</h3> <p>In this section, we discuss the lesser known forest elephants. ...this section continues... <h3>Mongolian gerbils</h3> <p>Hordes of gerbils have spread their range far beyond Mongolia. ...this subsection continues... <h2>Reptiles</h2> <p>Reptiles are animals with cold blood. ...this subsection continues... </section> </body>
形成如下的大纲:
1. Mammals 1.1 Whales (implicitly defined by the h2 element) 1.2 Forest elephants (explicitly defined by the section element) 1.3 Mongolian gerbils (implicitly defined by the h3 element, which closes the previous section at the same time) 2. Reptiles (implicitly defined by the h2 element, which closes the previous section at the same time)
这并不是一眼就可以通过标题标记就可以看出来的大纲。为了使标记容易理解,用显式的标记开始和闭合节段以及匹配标题等级与期望的嵌套节段等级。然而,HTML5规范并不需要这样。如果你发现浏览器以不期望的方式渲染文档,检查是否有隐式的节段没有闭合。
一个经验法则就是标题级别应该与节段嵌套级别相匹配,方便节段在多个文档中的重用。例如,一个节段可能会存储在内容管理系统中并在运行时组装为完整的文档。在这种情况下,好的实践便是使用<h1>
作为可重用部分的最高标题级别。可重用部分的嵌套级别应该取决于节段在文档结构中的出现位置。显式节段标记仍然在这种情况下有用处。
分节根
分节根是一个HTML元素,这个元素可以拥有自己的大纲,但是元素内部的节段和标题对其祖先的大纲没有贡献。与文档的逻辑分节根<body>
元素相比,这些元素经常在页面中引入外部内容:<blockquote>
, <details>
, <fieldset>
, <figure>
和<td>
。
Example:
<section> <h1>Forest elephants</h1> <section> <h2>Introduction</h2> <p>In this section, we discuss the lesser known forest elephants</p> </section> <section> <h2>Habitat</h2> <p>Forest elephants do not live in trees but among them. Let's look what scientists are saying in "<cite>The Forest Elephant in Borneo</cite>":</p> <blockquote> <h1>Borneo</h1> <p>The forest element lives in Borneo...</p> </blockquote> </section> </section>
例子形成如下的大纲:
1. Forest elephants 1.1 Introduction 1.2 Habitat
这个大纲并不包含 <blockquote>
元素的内部大纲。<blockquote>
元素是一个外部引用,是一个分节根并隔离了他内部的大纲
大纲之外的节段
HTML5引入了4个新的元素,用来定义那些不属于web文档主要大纲中的节段。
- HTML 侧边分节元素 (
<aside>
) 定义了这样的节段, 虽然是主要的分节元素, 但并不属于主要的文档流, 就像解释栏或广告栏. aside元素内部有自己的大纲,但并不计入文档大纲中 - HTML 导航分节元素 (
<nav>
) 定义的节段包含了很多导航links。文档中可以有好几个这样的元素,比如文档内部的链接,就像目录,和链接到其他站点的导航links。这些链接并不是主文档流和文档大纲中的一部分 ,并且能够特别让屏幕浏览器和类似的辅助技术从一开始就不渲染该标记里的内容。 - HTML 头部分节元素 (
<header>
) 定义了页面的头部,通常会包含logo和站点名称以及可能有的水平菜单. 尽管名字是header,但是不一定是在页面的开始 - HTML 脚部分节元素 (
<footer>
) 定义了页脚, 通常会包含版权信息和法律声明以及一些其他链接。同样,其不一定是在页面的底部出现。
分节元素中的地址和发表时间
文档的作者想要发布一些联系信息,例如作者的名字和地址。HTML4通过<address>
元素来表示,HTML5则拓展了这个元素。
一个文档可以由不同作者的不同节段组成。一个从其他作者而不是文档作者写的节段用<article>
元素定义。因此, <address>
元素连接到距离最近的<body>
或<article>
祖先元素。
同样的,新的HTML5标记 <time>
元素,使用pubdate
布尔值,表示整个文档的发布时间,分别给文章,与其最近的<body>
元素或<article>
元素的祖先元素相关。
在不支持HTML5的浏览器器中使用HTML5
分节和标题元素应该在大部分的不支持HTML5的浏览器中工作。尽管不支持,但不必使用特殊的DOM接口。仅仅只需要一个特殊的CSS样式,因为未知元素默认会样式化为display:inline:
section, article, aside, footer, header, nav, hgroup { display:block; }
当然web开发者可以改变上面的样式结构,但是要记住的是在不支持HTML5浏览器中,这些元素默认的样式是与预期的样式是不同的。还要注意的是<time>
元素并没有在这些元素中,因为其样式在不支持HTML5和兼容HTML5的浏览器中的表现是相同的。
然而这种方法有自己的局限性,因为一些浏览器并不允许样式化不支持的元素。这种情形出现在ie8及ie8以前的浏览器中,需要一个特殊脚本才行:
<!--[if lt IE 9]> <script> document.createElement("header" ); document.createElement("footer" ); document.createElement("section"); document.createElement("aside" ); document.createElement("nav" ); document.createElement("article"); document.createElement("hgroup" ); document.createElement("time" ); </script> <![endif]-->
这段脚本表示,当在ie8(及ie8以前)的情况下,应该允许脚本的运行以合适地展示HTML5分节和标题元素。如果禁用了脚本,则不会显示,可能会出问题因为这些元素定义整个页面的结构。为了预防这种情况,我们需要加上<noscript>
标签。
<noscript> <strong>Warning !</strong> Because your browser does not support HTML5, some elements are simulated using JScript. Unfortunately your browser has disabled scripting. Please enable it in order to display this page. </noscript>
于是形成了如下的代码,允许HTML5节段和标题元素在不支持HTML5的浏览器中展示,即使是ie8(ie8以下版本)也在禁用脚本的情况下有了合适的反馈。
<!--[if lt IE 9]> <script> document.createElement("header" ); document.createElement("footer" ); document.createElement("section"); document.createElement("aside" ); document.createElement("nav" ); document.createElement("article"); document.createElement("hgroup" ); document.createElement("time" ); </script> <noscript> <strong>Warning !</strong> Because your browser does not support HTML5, some elements are simulated using JScript. Unfortunately your browser has disabled scripting. Please enable it in order to display this page. </noscript> <![endif]-->
总结
HTML5中新的节段和标题标签带来了以标准的方法来描述web文档的结构和大纲。其为人们使用HTML5浏览器和需要结构来帮助他们理解页面带来了一个很大的优势。例如,人们需要一些辅助技术的帮助。这些新的语义元素使用简单,几乎没有负担,也可以在不支持HTML5的浏览器中工作。因此,他们应该被广泛使用。