CUED-迅雷用户体验设计中心

HTML大纲算法对结构的影响

           

HTML5已经出来好长时间了,越来越多人希望并且开始把HTML5应用到平时的工作、个站中。大家对section、article、aside、nav等新标签的使用也越来越上手,也许是自我感觉良好的上手。不从多个方面去认识理解这些标签,可能反而让自己落入了更混乱的境地。HTML的大纲算法(outlining algorithm)就是一个很重要的切入点。

先看两个大纲:

这两个都是我早期的作品了。当时还觉得自己的结构写的不错,特别是第二个,还用上了HTML5标签,以为自己就踏进这个新世界了。看过HTML大纲算法之后,检测了一下这些页面,真的是惨不忍睹。第一个各种混乱标题不说,“主创阵容”居然从属于“用户评论”?第二个也不好发言了,那么多未命名的是什么东西?不过总是要踩在伤痛的历史上才能往前进。

再来看几个其他人重构的页面大纲:

想象你是一个有点视力障碍的用户,需要依靠屏幕阅读器来浏览这些网页,阅读器会按照层级来给你解读这个网页,你觉得上面那个网页更容易让你获得所需要的资讯呢?也许对比完大家更想知道大纲算法到底是个怎么样的东西了吧?

什么是HTML大纲算法?

大纲算法允许用户代理(user agent)从一个web页面生成一个信息结构目录,让用户对页面有一个快速的概览。类似书籍、PDF、帮助文档等,都有一个清晰的目录结构,用户能方便的定位所需内容。一个良好结构的大纲,不仅是对于搜索引擎的优化,更是为借助于屏幕阅读器浏览网页的盲人(或弱视力)用户提供了巨大的帮助。

帮助文档的目录结构:

每个页面都有大纲,先从一个简单的例子来了解web页面大纲吧。假设要做一个电影介绍页面,主题是8月电影推介,页面结构也许如下:

1.8月电影推介
  1.国内电影
    1.《四大名捕》
    2.《搜索》
  2.国外电影
    1.《冰川时代4》
    2.《在劫难逃》

HTML4或者之前,我们都是采用hn(h1~h6)来生成大纲的。HTML5引入了section、article、aside、nav等新的节点元素(sectioning content),添加了一些新的规则,后面会详细阐述。

hn生成的大纲

也许HTML4的结构会这样写:

<div>
  <h1>8月电影推介</h1>

  <h2>国内电影</h2>
  <h3>《四大名捕》</h3>
  <p>四大名捕讲的是..</p>
  <h3>《搜索》</h3>
  <p>搜索讲的是..</p>

  <h2>国外电影</h2>
  <h3>《冰川时代4》</h3>
  <p>冰川时代4讲的是..</p>
  <h3>《在劫难逃》</h3>
  <p>在劫难逃讲的是..</p>

  <p>以上内容由迅雷看看提供</p>
<div>

可以看出,网页大纲由标题的层级来生成。

如果想要查看这段代码的大纲,可以试试Geoffrey Sneddon做的大纲工具Outliner(强烈推荐),上传文件和输入片段代码都可以。如果想要查看在线网页的大纲,可以给浏览器安装插件:chrome:HTML5 Outliner(推荐)/ Web Devoloper,firefox:Web Devoloper;opera:HTML5 Outliner。(HTML5 Outliner里中文会显示乱码,建议换成英文测试。浏览器插件可以显示中文)

每个标题都会生成一个隐性节点(implicit section),紧随其后的相对层级低的标题会成为它的子节点,层级相同或者更高的标题则会关闭这个节点并生成新的节点。可以测试一下下面的代码:

<h3>《四大名捕》</h3>
<p>四大名捕讲的是..</p>
<h3>《搜索》</h3>
<p>搜索讲的是..</p>

或者:

<h3>《搜索》</h3>
<p>搜索讲的是..</p>
<h2>国外电影</h2>

节点元素生成的大纲

也许HTML5的结构会这样写:

<div>
  <h6>8月电影推介</h6>

  <section>
    <h1>国内电影</h1>
    <article>
      <h1>《四大名捕》</h1>
      <p>四大名捕讲的是..</p>
    </article>
    <article>
      <h3>《搜索》</h3>
      <p>搜索讲的是..</p>
    </article>
  </section>

  <section>
    <h5>国外电影</h5>
    <article>
      <h6>《冰川时代4》</h6>
      <p>冰川时代4讲的是..</p>
    </article>
    <article>
      <h1>《在劫难逃》</h1>
      <p>在劫难逃讲的是..</p>
    </article>
  </section>

  <p>以上内容由迅雷看看提供</p>
<div>

(可以先注意一下上面这段代码的各个hn)把代码复制到Outliner工具去查看,很惊讶的发现,生成的大纲跟层级写的很漂亮的HTML4一样。为什么hn的层级在这里没有表现出来?

原因是此时大纲是由节点元素生成的,而非标题元素。HTML5的新标签section、article、aside、nav会生成显性节点(explicit sections),每个显性节点内部又有它自己的标题结构(当然也符合HTML4、HTML5大纲算法)。这也就是为什么HTML5允许多个h1存在的原因,不过,在全部浏览器、屏幕阅读器都完美支持HTML5之前,建议还是需要同时考虑标题结构,优雅降级。所以上面的结构可以改成这样:

<div>
  <h1>8月电影推介</h1>

  <section>
    <h2>国内电影</h2>
    <article>
      <h3>《四大名捕》</h3>
      <p>四大名捕讲的是..</p>
    </article>
    <article>
      <h3>《搜索》</h3>
      <p>搜索讲的是..</p>
    </article>
  </section>

  <section>
    <h2>国外电影</h2>
    <article>
      <h3>《冰川时代4》</h3>
      <p>冰川时代4讲的是..</p>
    </article>
    <article>
      <h3>《在劫难逃》</h3>
      <p>在劫难逃讲的是..</p>
    </article>
  </section>

  <p>以上内容由迅雷看看提供</p>
<div>

这里有另外一个问题值得注意,就是“以上内容由迅雷看看提供”这段话指的是上面的哪部分内容?在HTML4结构里,这段话是从属于隐性节点“《在劫难逃》”的,但明显不对。HTML5大纲算法就很好地解决了这个问题。

hn和节点元素同时生成大纲

如果页面里既有隐性节点(h1~h6)又有显性节点(section等),大纲又会如何生成呢?只要记住一点:显性节点能包含隐性节点,反之则不行。

<h1>8月电影推介</h1>
<section>
  <h2>国内电影</h2>
  <h3>《四大名捕》</h3>
  <p>四大名捕讲的是..</p>
  <h3>《搜索》</h3>
  <p>搜索讲的是..</p>
</section>

(代码1)

这段代码的大纲会是:

1.8月电影推介
  1.国内电影
    1.《四大名捕》
    2.《搜索》

 

<h1>8月电影推介</h1>
<h2>国内电影</h2>
<article>
  <h3>《四大名捕》</h3>
  <p>四大名捕讲的是..</p>
</article>
<article>
  <h3>《搜索》</h3>
  <p>搜索讲的是..</p>
</article>

然而这段代码的大纲会是:

1.8月电影推介
  1.国内电影
  2.《四大名捕》
  3.《搜索》

由标题元素生成的隐性节点遇上由节点元素生成的显性节点就会关闭并生成下一个同级节点。

未命名节点(untitled sections)

HTML5新节点元素除了section、article还有aside、nav,我们也来使用一下。

<nav>
  <ul>
    <li><a href="">首页</a></li>
    <li><a href="">专题</a></li>
    <li><a href="">关于</a></li>
  </ul>
</nav>
<h1>8月电影推介</h1>
<section>
  <h2>国内电影</h2>
</section>
<section>
  <h2>国外电影</h2>
</section>

复制到outliner会发现, nav标签会产生一个untitled section,因为nav里并没有给予任何标题元素。这不是错误也不会被认为是不好的HTML5结构。但是section、article还是建议给予适当的标题。如果不确定可以给予什么标题,也许使用div更适合,不要忘了我们还有div啊。

根节点

前面提到一个重要的原则:显性节点能包含隐性节点,反之则不行。也许你会注意代码1生成的大纲:

1.8月电影推介
  1.国内电影
    1.《四大名捕》
    2.《搜索》

标题元素h1(“8月电影推介”)下紧跟着的节点元素section(“国内电影”),变成了它的一个子节点。隐性节点不是不能包含显性节点么?这时候就需要认识一下根节点了。

根节点可以生成自己的大纲,它的标题和节点对祖先的大纲没有任何影响(而且不会出现在祖先大纲里)。目前有六个根节点:

1.body

2.blockquote

3.details

4.fieldset

5.figure

6.td

可以测试一下:

<h1>我是老大 I'm the big brother</h1>
<blockquote>
  <section>
    <h1>我是blockquote里的老大,待会你看不到我了 I'm the big brother in blockquote,you'll not find me in the outliner</h1>
  </section>
</blockquote>
<h2>我是老二 I'm the younger</h2>

定义文档里说明了:节点元素是离它最近的祖先根节点或节点元素的子节点。代码1里的标题元素h1(“8月电影推介”)是body的标题,节点元素section(“国内电影”)是body的子节点。

还有一个很重要的:文档的标题是文档中第一个且非节点元素里的标题元素。测试一下下面的代码就很明了了:

<section>
  <h1>我很想成为文档的标题可惜不能 I want to be the title but I couldn't</h1>
</section>
<h6>虽然我层级最小可是我是第一个出现的 I'm h6 but I come first</h6>
<h1>最大也没用顺序我还是在老6下面 I'm h1 but I come after h6</h1>

过程中我还遇到过另一个让我迷惑的:

<section>
  <h1>我很想成为文档的标题可惜不能 I want to be the title but I couldn't</h1>
</section>
<section>
  <h2>我也很想成为文档的标题可惜不能 Me either:(</h2>
</section>
<footer>
  <h3>我是footer可是为什么我成为了文档标题啊 I'm footer but why I become the title??</h3>
</footer>

原因很简单,header和footer不是节点元素。

hgroup

hgroup很好理解也很好用,它的作用就是帮你添加副标题而不影响文档大纲,大纲中只会出现层级最高的标题,无论出现顺序。

<hgroup>
  <h3>我是副标题,我很重要但我不会出现在大纲中 I'm your loved second title,I'm useful and I won't appear in the outliner</h3>
  <h2>我是大标题,我是故意跑到下面来的 I'm the highest level of hn in the group,no matter where I am,I will be part of ouliner</h2>
</hgroup>

总结

到写完这篇文章为止,好像还没有哪个浏览器是完美支持HTML5大纲算法的。但这不影响我们对HTML5大纲算法的学习,就像我们现在在努力使用HTML5+CSS3一样。理解了HTML5大纲算法,不仅对于新标签的使用有更进一步的认识,而且对于最根本的页面结构有更优化的理解,就算只是标题元素生成的大纲,也能拥有完美的层级结构,这也是语义化的一个标志。

特别感谢一下大安仔,是他提醒我要注意这个问题的。

参考学习文章:

http://www.osmn00.com/rebuild/223.html

http://www.456bereastreet.com/archive/201103/html5_sectioning_elements_headings_and_document_outlines/

http://coding.smashingmagazine.com/2011/08/16/html5-and-the-document-outlining-algorithm/

http://html5doctor.com/outlines/

https://developer.mozilla.org/en-US/docs/Sections_and_Outlines_of_an_HTML5_document

  1. 你们都好厉害,我真不知我该咋办了

  2. […] HTML5已经出来好长时间了,越来越多人希望并且开始把HTML5… 阅读全文>> 评论[34] […]

  3. […] 原文链接:http://cued.xunlei.com/log047 […]

  4. 分析的很正确,很好。学习了

  5. 传说中的语义化!

  6. bengle 说:

    给力的分享,赞!!

  7. […]     以前知道在网页里面H标签是用来对网页内容分级的,知道了有文档大纲这个概念,后来接触了html5,讲到了显示编排和隐示编排,知道了一个概念,在使用中也没什么大问题就没在在意,最近看了迅雷的一篇文章,获益匪浅啊。看来以前还是走入了一些误区里面。 […]

  8. […] 文章来源:迅雷CUED 返回 […]

  9. 不知不觉又开学了,暑假本来打算学习wordpress,但被其他事情耽搁了,杯具啊

  10. iphone5 说:

    有时间记得更新哦,博主。咱偶尔会来看看

  11. KanCBA 说:

    第一次来贵博客,很好,很受教,拜读了,以后会常来。

  12. iphone4s 说:

    html5最好的就是不需要插件可以放视频,不过很多网站还不支持

  13. iphone5 说:

    今天的编辑工作提前完成,逛逛博客,留个小爪子,哈哈

  14. we_see_t 说:

    非常强大啊!

  15. 说:

    文章很不错,强烈支持一下!!!

  16. we_see_t 说:

    好文章!

  17. 看了一下这个页面:http://topics.xunlei.com/qtfy/
    个人认为,有几点可以加强一下
    1. 主体banner 采用 img 方式插入就更好了(优先渲染);
    2.优化整个页面需要图片替换文字的地方,在图片未加载的时候可以正常显示文字,而不是使用 text-indent 的方式;
    3.最好在浮动元素的父级闭合一下浮动,减少意外,让页面模块更加健壮。

  18. 再次认识到大纲对于可用性的增强,之前没有太注意这个问题,以后会多多优化结构。

  19. 跳跳 说:

    文中的那个Chrome浏览器扩展是什么?

  20. 贸易网 说:

    好久没看到这么牛的技术文章了,更何况是个女强人的

  21. 麦时 说:

    赞七宝!

  22. HTML5显然越来越人性化了、

  23. 还以为是男士写的,女士也这么牛

  24. […] 转自迅雷Ued QQ空间 新浪微博 腾讯微博 人人网 百度搜藏 百度贴吧 QQ收藏 更多 document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion=&quot; + new Date().getHours(); […]

  25. yao 说:

    七宝厉害··········

  26. 博主你的主题不错,更新到3.0以上了吗?

  27. iphone5 说:

    奥运会结束了,可以专心写点独家文章,欢迎互访:-)

  28. 说:

    高级

  29. leon 说:

    V5+MAX!

  30. 小强 说:

    以前完全不知道html5还有显性节点标签,仅以为nav这类标签只是为spider语义化而生的。看过之后才发现这才是html5 <nav>这类显性节点标签的真正意义所在。而不是仅仅把<nav>标签当做<div class="nav" >来使用。从语义和实际作用上都有体现。
    这样一来我觉得,在手机或者处理网页文章阅读器方面又有新方法了。
     

  31. happyTIME_2 说:

    七宝v5

发表你的评论