RM8024: 各浏览器对除 TABLE 之外的表格类元素以及它们相对于 CSS 中 display 特性值的相对定位特性的支持存在差异
一、问题发现
最近的新网站上线,发现了一个bug,这个bug居然只出现FireFox下!截个图上来就清楚了:
期待的正常的效果:
![]()
FireFox下的效果:
![]()
很明显,在FireFox下,出游计划的日历飘到导航栏上了。它的文档结构是这样的:
![]()
红色框就是日历所在的单元格,被一个div.calendar-panel包裹着,存在于一个表格里面。样式表中,td.calender-td使用了“position:relative;”,div.calendar-panel使用了“position:absolute;”这样来布局的。这样的布局在合模型里面是再正常不过了,难怪在其他浏览器中显示均正常。可是这里的“position:relative;”是作用于td,一个表格类型元素,合模型的效果在这里似乎就不是这么回事了。
很自然地,直观上就能嗅出问题所在:日历没有相对单元格定位,而是相对父级section.container定位,因为它定义了“position:relative;”。
那么为什么td的相对定位失效呢?为什么只有在FireFox下才失效呢?
二、问题解决
只能说FireFox真的是太标准的浏览器了,我在网上找了找资料,发现一篇文章讲到了这个问题,写的不错!文章地址:http://www.w3help.org/zh-cn/causes/RM8024
总结起来就是,表格类型元素的display值在不同浏览器显示效果有差异。
下面我将这篇文章转载+修改过来,因为原文的测试时间是2010年10月15日,原文的浏览器测试版本相对较旧,笔者使用当前较新版本的浏览器重新测试了一遍,将测试结果写在下文中。
RM8024: 各浏览器对除 TABLE 之外的表格类元素以及它们相对于 CSS 中 display 特性值的相对定位特性的支持存在差异
标准参考
根据 CSS2.1 规范中的描述,被设定了 ‘position’ 特性值为 ‘relative’ 的框的位置会根据其在普通流 (normal flow) 的位置进行计算。然后此框会相对于 (relative) 它在普通流中的位置进行偏移。如果一个框 B 是相对定位的,则其随后的框的定位计算并不考虑 B 的偏移。
‘position:relative’ 作用在 table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption 这些类型元素上的效果并未定义。
CSS 中的表格模型基于 HTML4 的表格模型,包括了表格,标题,行,行组,列,列组以及单元格。下列 ‘display’ 特性的值可以将表格语义指派给一个任意的元素:
|
‘display’ 特性的值 |
对应 HTML 中的元素 |
| table-row | TR |
| table-row-group | TBODY |
| table-header-group | THEAD |
| table-footer-group | TFOOT |
| table-column | COL |
| table-column-group | COLGROUP |
| table-cell | TD, TH |
| table-caption | CAPTION |
关于 CSS 表格模型 特性的更多信息,请参考 CSS2.1 规范 17.2 The CSS table model 中的内容。
问题描述
在 IE6 IE7 IE8(Q) 中,TD/TH 及 TD 元素对设定 ‘position:relative’ 特性及偏移有效,其他均无效;
在 IE8(S) 中,TD/TH 及 CAPTION 元素及它们相对于 CSS 中 display 特性值对设定 ‘position:relative’ 特性及偏移有效,其他均无效;
在 Firefox 中,除 TABLE 之外的所有表格类元素以及它们相对于 CSS 中 display 特性值对设定 ‘position:relative’ 特性及偏移均无效
在 Chrome Safari 中,CAPTION 元素及它相对于 CSS 中 display 特性值 ‘caption’ 对设定 ‘position:relative’ 特性及偏移有效,其他均无效;
在 Opera 中,COL、COLGROUP 元素以及它们相对于 CSS 中 display 特性值对设定 ‘position:relative’ 特性及偏移无效,其他均有效。
造成的影响
此问题可能导致设定了相对定位的符合问题描述的元素的位置在不同浏览器中产生差异,从而影响布局甚至功能实现。
受影响的浏览器
所有浏览器
问题分析
CSS2.1 规范中直接说明了 ‘position:relative’ 作用在 table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption 这些类型元素上的效果并未定义。
下面就对 HTML 中除 TABLE 之外的表格类元素 (包括 TD/TH、TR、THEAD、TBODY、TFOOT、COL、COLGROUP、CAPTION) 以及它们相对于 CSS 中 ‘display’ 特性值 (包括 ‘table-cell’、’table-row’、’table-header-group’、’table-row-group’、’table-footer-group’、’table-column’、’table-column-group’、’table-caption’) 对 ‘position:relative’ 的效果进行分析。
1. 为 TD 元素设定 ‘position:relative’
分析以下代码:cell_relative.html
<!DOCTYPE html> <html> <head> <style> * { margin:0; font:20px/1.5 'Trebuchet MS'; } table { border:5px solid black; background:khaki; } td { border:2px solid navy; background:mistyrose; } </style> </head> <body> <table cellpadding="2" cellspacing="5"> <tr> <td>static</td> <td>static</td> <td>static</td> </tr> <tr> <td>static</td> <td style="position:relative; left:30px; top:30px; background:lightskyblue;">relative</td> <td>static</td> </tr> <tr> <td>static</td> <td>static</td> <td>static</td> </tr> </table> </body> </html>
上面代码为中间的 TD 元素设置了 position:relative 以及其偏移。
在各浏览器中效果如下:
|
IE6 IE7 IE8 IE9 Opera Chrome Safari |
Firefox |
|  |  |
2. 为 TR 元素设定 ‘position:relative’
分析以下代码:row_relative.html
<!DOCTYPE html> <html> <head> <style> * { margin:0; font:20px/1.5 'Trebuchet MS'; } table { border:5px solid black; background:khaki; } td { border:2px solid navy; background:mistyrose; } </style> </head> <body> <table cellpadding="2" cellspacing="5"> <tr> <td>static</td> <td>static</td> </tr> <tr style="position:relative left:30px; top:30px;"> <td style="background:lightskyblue;">relative</td> <td style="background:lightskyblue;">relative</td> </tr> <tr> <td>static</td> <td>static</td> </tr> </table> </body> </html>
上面代码为中间的 TR 元素设置了 position:relative 以及其偏移。
在各浏览器中效果如下:
|
IE6 IE7 IE8(Q) Opera |
IE8(S) IE9 Firefox Chrome Safari |
|  |  |
3. 为其他表格类元素 COL、COLGROUP、THEAD、TBODY、TFOOT、CAPTION 设定 ‘position:relative’
分析以下代码:other_relative.html
<!DOCTYPE html> <html> <head> <style> * { margin:0; font:20px/1.5 'Trebuchet MS'; } table { border:5px solid black; background:khaki; } td { border:2px solid navy; background:mistyrose; } </style> </head> <body> COL <table cellpadding="2" cellspacing="5"> <col style="position:relative left:200px;" /> <tr> <td>COL</td> <td>COL</td> </tr> </table> <br /> COLGROUP <table cellpadding="2" cellspacing="5"> <colgroup style="position:relative left:200px;"> <col /> </colgroup> <tr> <td>COLGROUP</td> <td>COLGROUP</td> </tr> </table> <br /> THEAD, TBODY, TFOOT <table cellpadding="2" cellspacing="5"> <thead style="position:relative left:100px;"> <tr> <td>THEAD</td> </tr> </thead> <tbody style="position:relative left:120px;"> <tr> <td>TBODY</td> </tr> </tbody> <tfoot style="position:relative left:140px;"> <tr> <td>TFOOT</td> </tr> </tfoot> </table> <br /> CAPTION <table cellpadding="2" cellspacing="5"> <caption style="position:relative left:100px; background:lightskyblue;">CAPTION</caption> <tr> <td>table cell</td> </tr> </table> </body> </html>
上面代码为 COL、COLGROUP、THEAD、TBODY、TFOOT、CAPTION 元素设置了 position:relative 以及其偏移。
在各浏览器中效果如下:
|
IE6 IE7 IE8(Q) Firefox |
IE8(S) IE9 Chrome Safari |
Opera |
|  |  |  |
4. CSS 中 ‘display’ 特性值为 ‘table-cell’、’table-row’、’table-header-group’、’table-row-group’、’table-footer-group’、’table-column’、’table-column-group’、’table-caption’ 的元素设定 ‘position:relative’
上面测试的均为 HTML 中原生为表格类的元素,下面将分析通过设定 ‘display’ 特性1来模拟表格特性的元素对 ‘position:relative’ 是否有效。
注 1: 由于 IE6 IE7 IE8(Q) 不支持上述 ‘display’ 特性值,故下面将只考虑 IE8(S) 和IE9及其他非 IE 浏览器。
分析以下代码:dis_relative.html
<!DOCTYPE html> <html> <head> <style> * { margin:0; padding:0; font:12px/1 'Trebuchet MS'; } h1 { font-weight:bold; border-top:2px solid gray; } .table { display:table; border-spacing:5px; border:5px solid black; background:khaki; } .tr { display:table-row; } .td { display:table-cell; border:2px solid navy; background:mistyrose; padding:2px; } .thead { display:table-header-group; } .tbody { display:table-row-group; } .tfoot { display:table-footer-group; } .caption { display:table-caption; } .col { display:table-column; } .colgroup { display:table-column-group; } </style> </head> <body> <div class="table"> <div class="tr"> <div class="td">table-cell</div> <div class="td">table-cell</div> </div> <div class="tr"> <div class="td" style="position:relative; left:30px; top:20px; background:lightskyblue;">table-cell</div> <div class="td">table-cell</div> </div> <div class="tr"> <div class="td">table-cell</div> <div class="td">table-cell</div> </div> </div> <br /> <div class="table"> <div class="tr"> <div class="td">table-row</div> <div class="td">table-row</div> </div> <div class="tr" style="position:relative; left:30px; top:20px;"> <div class="td" style="background:lightskyblue;">table-row</div> <div class="td" style="background:lightskyblue;">table-row</div> </div> <div class="tr"> <div class="td">table-row</div> <div class="td">table-row</div> </div> </div> <br /> <div class="table"> <div class="thead" style="position:relative; left:80px; top:20px;"> <div class="tr"> <div class="td" style="background:lightskyblue;">table-header-group</div> </div> </div> </div> <br /> <div class="table"> <div class="tbody" style="position:relative; left:80px; top:20px;"> <div class="tr"> <div class="td" style="background:lightskyblue;">table-row-group</div> </div> </div> </div> <br /> <div class="table"> <div class="tfoot" style="position:relative; left:80px; top:20px;"> <div class="tr"> <div class="td" style="background:lightskyblue;">table-footer-group</div> </div> </div> </div> <br /> <div class="table"> <div class="caption" style="position:relative; left:80px; top:20px; background:lightskyblue;">table-caption</div> <div class="tr"> <div class="td">table-caption</div> </div> </div> <br /> <div class="table"> <div class="col" style="position:relative; left:200px;"></div> <div class="tr"> <div class="td">table-column</div> <div class="td">table-column</div> </div> </div> <br /> <div class="table"> <div class="colgroup" style="position:relative; left:200px;"> <div class="col"></div> </div> <div class="tr"> <div class="td">table-column-group</div> <div class="td">table-column-group</div> </div> </div> </body> </html>
上面代码上面代码中为 ‘display’ 特性值为 ‘table-cell’、’table-row’、’table-header-group’、’table-row-group’、’table-footer-group’、’table-column’、’table-column-group’、’table-caption’ 的 DIV 元素设置了 position:relative 以及其偏移。
在各浏览器中效果如下:
|
IE8(S) IE9 Chrome Safari |
Firefox |
Opera |
|  |  |  |
5. 小结
下面通过表格总结各浏览器对除 TABLE 之外的表格类元素以及它们相对于 CSS 中 ‘display’ 特性值设置相对定位 (position:relative) 特性的支持差异:
|
IE6 IE7 IE8(Q) |
IE8(S) IE9 |
Chrome Safari |
Firefox |
Opera |
|
| CAPTION (display:table-caption) |
无效 |
有效 |
有效 |
无效 |
有效 |
| THEAD (display:table-header-group) |
无效 |
无效 |
无效 |
无效 |
有效 |
| TBODY (display:table-row-group) |
无效 |
无效 |
无效 |
无效 |
有效 |
| TR (display:table-row) |
有效 |
无效 |
无效 |
无效 |
有效 |
| TD/TH (display:table-cell) |
有效 |
有效 |
无效 |
无效 |
有效 |
| TFOOT (display:table-footer-group) |
无效 |
无效 |
无效 |
无效 |
有效 |
| COL (display:table-column) |
无效 |
无效 |
无效 |
无效 |
无效 |
| COLGROUP (display:table-column-group) |
无效 |
无效 |
无效 |
无效 |
无效 |
解决方案
由于除 TABLE 之外的表格类元素以及它们相对于 CSS 中 display 特性值设定了相对定位后的效果 CSS2.1 规范中没有明确定义,而各浏览器的实现又存在很大差异。所以应避免为这些元素设定 ‘position:relative’。
若需要实现如冻结表格行或列的效果,可以考虑使用绝对定位其他 TABLE 元素的方式模拟。
测试环境
操作系统版本:
Windows 7 Ultimate build 7600
浏览器版本:
IE6
IE7
IE8
IE9
Firefox 11.0
Chrome 16.0.912.75
Safari 5.1.5(7534.55.3)
Opera 11.62
测试页面:
cell_relative.html
row_relative.html
other_relative.html
dis_relative.html
本文更新时间:
2012-04-02