W3C HTML5标准阅读笔记 – 元素分类与内容模型(Content Model)

标准原文:http://www.w3.org/TR/html5/dom.html#content-models

HTML4中,元素被分成两大类: inline(内联元素)与block(块级元素)。但在实际的开发过程中,因为页面表现的需要,前端工程师经常把inline元素的display值设定为block(比如a标签),也经常把block元素的display值设定为inline;之后更是出现了inline-block这一对外呈现inline、对内呈现block的属性。因此,简单地把HTML元素划分为inline与block已经不再符合实际需求。

基于这种考虑,在HTML5中,标准制定者重新定义了HTML元素的分类,并根据这一新的分类定义了元素的内容模型(Content Model) -- 对于一个元素而言,哪些子元素是合法的,而哪些子元素是非法的。

HTML5中,元素主要分为7类:

  • Metadata
  • Flow
  • Sectioning
  • Heading
  • Phrasing
  • Embedded
  • Interactive

这些分类集合互相之间也存在一定的交集(一个元素可以同时属于多个分类),其交集关系呈现为:

content model diagram

需要注意的是,HTML5中的这种元素分类与inline、block没有任何关系,任何元素都可以在CSS中被定义为display:inline或者display:block。另外,除了这7大分类,还存在一些较小的分类,如Palpable、Script-Supporting等。

Metadata

顾名思义,Metadata元素意指那些定义文档元数据信息的元素 — 其作用包括:影响文档中其它节点的展现与行为、定义文档与其它外部资源之间的关系等。以下元素属于Metadata:base, link, meta, noscript, script, style, template, title

Flow

所有可以放在body标签内,构成文档内容的元素均属于Flow元素。因此,除了base, link, meta, style, title等只能放在head标签内的元素外,剩下的所有元素均属于Flow元素。

Sectioning

Sectioning意指定义页面结构的元素,具体包含以下四个:article, aside, nav, section

Heading

所有标题元素属于Heading,也即以下6个元素:h1, h2, h3, h4, h5, h6

Phrasing

所有可以放在p标签内,构成段落内容的元素均属于Phrasing元素。因此,所有Phrasing元素均属于Flow元素。在HTML5标准文档中,关于Phrasing元素的原始定义为:

Phrasing content is the text of the document, as well as elements that mark up that text at the intra-paragraph level. Runs of phrasing content form paragraphs.

对于这一定义,个人认为不应当使用“text”这一容易引起误解的词,事实上,一个元素即使不是文本,只要能包含在p标签中成为段落内容的一部分,就可以称之为Phrasing元素。比如:audio、video、img、select、input等元素(经测试,这些元素都可以放置在p标签中)。一个不太精确的类比是:HTML5中的Phrasing元素大致就是HTML4中所定义的inline元素。

Phrasing元素内部一般只能包含别的Phrasing元素。

关于Phrasing元素,Stackoverflow上有一个比较精彩的问答,可供参考。

Embedded

所有用于在网页中嵌入外部资源的元素均属于Embedded元素,具体包含以下9个:audio, video, img, canvas, svg, iframe, embed, object, math

Interactive

所有与用户交互有关的元素均属于Interactive元素,包括a, input, textarea, select等。

内容模型(Content Model)

根据以上元素分类,HTML5标准文档定义了任何元素的内容模型 — 对于该元素而言,何种子元素才是合法的。

比如,对于p元素而言,其内容模型为Phrasing, 这意味着p元素只接受Phrasing元素为子元素,而对于像div这样的非Phrasing元素则并不接受。类似的,li元素的内容模型为Flow,因此任何可以放置在body中的元素都可以作为li元素的子元素。

值得注意的是,HTML5标准文档在定义元素的内容模型时,会使用一类特殊的分类:透明内容模型(transparent) — 对于内容模型为透明(transparent)的元素而言,其子元素的合法性由其父元素所决定;如果其父元素的内容模型仍为透明,则查看其祖父元素的情况,并依此类推;如果向上推演至body标签仍未找到任何内容模型非透明的父级元素,则该透明元素内部可包含任何Flow元素。

典型的具有透明内容模型的元素为a元素。因此,当a出现在p标签中时,a不能接受div作为子元素;而当a出现在div标签中时,a可以接受div作为子元素。对此,知乎上有一个问答解释了这种现象:http://www.zhihu.com/question/34952563