#### 元素分类
HTML5中,元素主要分为7类:
1. Metadata 元数据元素
2. Flow 流式元素
3. Sectioning 章节元素
4. Heading 标题元素
5. Phrasing 段落元素
6. Embedded 嵌入元素
7. Interactive 交互元素
这些分类集合互相之间也存在一定的交集(一个元素可以同时属于多个分类),其交集关系呈现为:
![](https://box.kancloud.cn/381035d65808e068b6b9432252e2698f_512x288.png)
###### Metadata
Metadata元素意指那些定义文档元数据信息的元素 — 其作用包括:影响文档中其它节点的展现与行为、定义文档与其它外部资源之间的关系等。以下元素属于Metadata:
```
base, link, meta, noscript, script, style, template, title
```
###### Flow
所有可以放在body标签内,构成文档内容的元素均属于Flow元素。因此,除了base, link, meta, style, title等只能放在head标签内的元素外,剩下的所有元素均属于Flow元素。
```
a, abbr, address, area, article, aside, audio, b, bdi, bdo, blockquote, br, button, canvas, cite, code, command, datalist, del, details, dfn, div, dl,em, embed, fieldset, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, i, iframe, img, input, ins, kbd, keygen, label, map, mark, math, menu, meter,nav, noscript, object, ol, output, p, pre, progress, q, ruby, s, samp, script, section, select, small, span, strong, style(如果该元素设置了scoped属性), sub, sup, svg, table,textarea, time, u, ul, var, video, wbr, text
```
###### Sectioning
Sectioning意指定义页面结构的元素,具体包含以下四个:
```
article, aside, nav, section
```
###### Heading
所有标题元素属于Heading,也即以下6个元素:
```
h1, h2, h3, h4, h5, h6
```
###### Phrasing
所有可以放在p标签内,构成段落内容的元素均属于Phrasing元素。因此,所有Phrasing元素均属于Flow元素。
对于这一定义,个人认为不应当使用“text”这一容易引起误解的词,事实上,一个元素即使不是文本,只要能包含在p标签中成为段落内容的一部分,就可以称之为Phrasing元素。
```
a(如果其只包含段落式元素), abbr, area, audio, b, bdi, bdo, br, button, canvas, cite, code, command, datalist, del(如果其只包含段落式元素), dfn, em, embed, i,iframe, img, input, ins(如果其只包含段落式元素), kbd, keygen, label, map(如果其只包含段落式元素), mark, math, meter, noscript, object, output, progress, q, ruby, s, samp, script,select, small, span, strong, sub, sup, svg, textarea, time, u, var, video, wbr, text
```
一个不太精确的类比是:HTML5中的Phrasing元素大致就是HTML4中所定义的inline元素。
Phrasing元素内部一般只能包含别的Phrasing元素。
###### Embedded
所有用于在网页中嵌入外部资源的元素均属于Embedded元素,具体包含以下9个:
```
audio, video, img, canvas, svg, iframe, embed, object, math
```
###### Interactive
所有与用户交互有关的元素均属于Interactive元素。
```
a, audio(如果设置了controls属性), button, details, embed, iframe, img(如果设置了usemap属性), input(如果type属性不为hidden状态), keygen, label, menu(如果type属性为toolbar状态),object(如果设置了usemap属性), select, textarea, video(如果设置了controls属性)
```
##### 内容模型(Content Model)
根据以上元素分类,HTML5标准文档定义了任何元素的内容模型 — 对于该元素而言,何种子元素才是合法的。
比如,对于p元素而言,其内容模型为Phrasing, 这意味着p元素只接受Phrasing元素为子元素,而对于像div这样的非Phrasing元素则并不接受。类似的,li元素的内容模型为Flow,因此任何可以放置在body中的元素都可以作为li元素的子元素。
值得注意的是,HTML5标准文档在定义元素的内容模型时,会使用一类特殊的分类:透明内容模型(transparent) — 对于内容模型为透明(transparent)的元素而言,其子元素的合法性由其父元素所决定;如果其父元素的内容模型仍为透明,则查看其祖父元素的情况,并依此类推;如果向上推演至body标签仍未找到任何内容模型非透明的父级元素,则该透明元素内部可包含任何Flow元素。
##### 正确嵌套标签
元素的嵌套规则和页面头部申明的DTD有着千丝万缕的关系,通过了解HTML5的元素分类与内容模型,我们能更清楚的指导我们元素的嵌套关系。虽然大部分浏览器都有容错机制,写出来的代码在浏览器下表现没有什么异样,但作为一个专业开发人员,我们必须对待自己的代码应该一丝不苟,即使HTML5的胸襟很宽广,但我们更应该去遵从W3C,因为只有标准健壮的代码,才会有更好的扩展与兼容。
因此a标签内是否合可以包含div标签要看其父元素的 content model 和其内容的 categories。比如我们要看 p > ins > a > div 是否合法,过程是这样的:p 元素的 content model 是 phrasing content,ins 本身属于 phrasing content 故可以嵌套;ins 元素的 content model 是 transparent,故在此时里面是否能有 a 需检查 p > a 的合法性;a 元素也属于 phrasing content,故 p > ins > a 合法;a 元素的 content model 也是 transparent,故此时里面包含 div 的合法性向上传递,检查 ins > div 又向上传递,变成检查 p > div;div 不属于 phrasing content,所以这个嵌套是不合法的。