为了在主流浏览器上使用HTML 5语义化标签,需要做一些修正,本文便是对这些修正原理的解释。
如果你正在寻找一个快速的解决方案,可以看以下HTML5 Shiv这个库。下载这个库的代码,然后在页面的head
中使用以下代码即可:
|
|
如果看看这个代码背后的原理,请继续往下。
HTML 5语义化标签简述
语义化标签,顾名思义,是具备一定语义的标签。比如,当使用ol
标签,语义就是创建一个有序的列表。语义化可以增强页面的可访问性。
一个页面通常会被划分成几个区域,比如头部,边栏,内容区域以及底部。在HTML 5之前,页面的结构代码看起来类似于:
|
|
由于这些结构划分的通用性,HTML 5引入了几个具有此类语义的标签:
|
|
使用这些标签重写上面的页面:
|
|
新标签与旧浏览器的冲突
有些浏览器早于HTML 5草案发布,所以这些浏览器可能不支持这些新的标签。这就存在着一个问题,那就是浏览器对于未知的标签(元素)是如何处理?这个问题可以再细分为两个子问题:
- 如何处理未知元素的样式
- 如何处理未知元素在DOM树中的位置
不同的浏览器对于这两点的处理是不同的,特别在老版本的IE中存在特殊的行为。
第一个修正
针对第一条(即未知元素的样式),对于浏览器来说,最为简单的做法是不对未知元素的样式做任何处理。浏览器会给已知元素设置一些默认的样式,比如i
标签,默认是斜体,p
标签具有前后留白等。而对于未知元素,浏览器没有给定任何的默认样式,由页面作者自定义其样式。
但需要注意的是,浏览器会将未知元素认为是inline
级别。所以对于旧版本的浏览器做的修正是明确指定新标签的display
规则:
|
|
针对IE的处理
事情还未结束,因为IE 9之前的版本对于未知元素的处理存在着两个问题:
- 无法应用样式到未知元素上
- 错误地解析未知元素为空节点
第一个问题是,即使在样式表中指定了未知元素的样式规则,同样无法生效。
第二个问题从解析后的DOM结构来看很明了。假定有如下的代码:
|
|
正确的渲染之后是如下的结构:
article
|
+--h1 (article子节点)
| |
| +--text node "Welcome to Initech"
|
+--p (article子节点)
|
+--text node "This is your "
在IE 9之前的版本中,article标签(未知元素)将被解析成一个空的标签,其子元素成为这个未知元素的相邻节点:
article (空节点)
h1 (article相邻节点)
|
+--text node "Welcome to Initech"
p (article相邻节点)
|
+--text node "This is your "
幸运的是,IE中这两个问题可以很简单的被修正。
对于未知元素,在页面渲染前使用document.createElement()
这个方法创建一次即可,不用注入到页面上。例如:
|
|
需要注意的是,必须在浏览器解析未知元素之前使用这个方法。所以建议是将这个hotfix放置在页面的head
区域中。
小結
为了在兼容当前主流浏览器的情况下使用HTML 5新的语义标签,需要做两个处理:
明确指定新标签的
display
属性header, main, aside, article, footer { display: block; }
针对IE 9以下版本的浏览器做处理。在页面
head
区域,使用以下代码:<!--[if lt IE 9]> <script type="text/javascript"> var e = ("abbr,article,aside,audio,canvas,datalist,details," + "figure,footer,header,hgroup,mark,menu,meter,nav,output," + "progress,section,time,video").split(','); for (var i = 0; i < e.length; i++) { document.createElement(e[i]); } </script> <![endif]-->
以上。