IE6浮动双倍margin

问题描述

当元素浮动并且定义了与浮动及书写方向一致的margin,这时,在IE6下margin值将表现为指定值的双倍,如果同一个包含块内有多个子元素浮动,那么只有和浮动方向一致元素的margin才会双倍,并且该元素是浮动方向上的第一个元素。

影响环境

windows/IE6

触发条件

问题重现

最小化代码重现问题:

CSS Code:

.demo{*zoom:1;overflow:hidden;background:#f00;} .demo .item{float:left;margin-left:15px;padding:5px 10px;background:#aaa;}

HTML Code:

<div class="demo"> <div class="item item1">子项一</div> <div class="item item2">子项二</div> <div class="item item3">子项三</div> </div>

预期效果:

(图一)

IE6效果如下:

(图二)

可以很明显的看到第1个子元素的左边距(CSS代码中定义的margin-left)比后2个都要宽,要告诉你的是,它正好是正常设定的2倍大小。

DEMO:

查看 DEMO1 并在IE6和其它浏览器下对比。

验证触发条件

list-item元素

真的是只有block和list-item元素才会触发此Bug吗?block元素我们已在 DEMO1 中验证过,再来验证list-item元素,html修改如下:

HTML Code:

<ul class="demo"> <li class="item item1">子项一</li> <li class="item item2">子项二</li> <li class="item item3">子项三</li> </ul>

当我们将元素list-item的li时,你会发现问题仍然存在,用事实说话:DEMO2

inline元素

我们接着验证inline元素,html修改如下:

HTML Code:

<div class="demo"> <span class="item item1">子项一</span> <span class="item item2">子项二</span> <span class="item item3">子项三</span> </div>

你会发现IE6居然也正常工作了,用事实说话:DEMO3

inline-block元素

验证inline-block元素,我们只能使用行内元素来进行,因为IE6不支持块元素直接通过display去转换为行内元素。所以干脆直接在 DEMO3 的基础上,将CSS修改如下:

CSS Code:

.demo .item{_display:inline-block;}

很明显,你也会得到一个在IE6下正常工作的代码,示例如下:DEMO4

验证描述

我们验证了 block | list-item | inline | inline-block 4种元素的情况,至于其它的就不用再验证了,因为IE6都不支持。准备的说只有 block和list-item元素 才能触发其实是不严谨的,应该说是 block level 都会触发。

简单说明一下几个概念吧:

这些概念很重要,不要混淆了,想更详细的了解这些信息,请自行Google至W3C。

问题产生原因

IE6排版引擎实现上的Bug,无原理和常规解释。

解决方案

虽然我们无法知道IE6的排版引擎在实现上为什么会有此Bug,但通过对触发条件的验证,我们知道了此问题只有block level元素才会触发,也就是说我们只需要修改display属性为非block level即可。同时,我们知道IE6只支持display属性的:none | inline | block | list-item | inline-block 5个值;而且对inline-block的支持只体现在行内元素上,行内元素不触发该Bug,于是没场景使用;你又不可能将元素隐藏,那么就只剩下inline可选。于是双倍边距Bug的最终解决方案只能是:

CSS Code:

display:inline

修正后的 DEMO5

其它

至于触发条件里的 margin定义与浮动及书写方向一致 是什么意思呢?这里只简单说一下,直接看代码比较容易:

CSS Code:

.demo{*zoom:1;overflow:hidden;background:#f00;} .demo .item{margin:0 15px;padding:5px 10px;background:#aaa;} .demo .item1,.demo .item2{float:left;} .demo .item3,.demo .item4{float:right;}

HTML Code:

<div class="demo"> <div class="item item1">子项一</div> <div class="item item2">子项二</div> <div class="item item3">子项三</div> <div class="item item4">子项四</div> </div>

你会发现item1item3 都双倍margin了,但方向却不同,item1是margin-left双倍,而item3是margin-right双倍。示例如下:DEMO6

这说明了什么呢?

首先说明双倍margin的方向和浮动方向有关,因为item1是左浮动,所以左边距才双倍,item3是右浮动,所以右边距才双倍;
其次,item1item3分别是包含块demo中左浮动和右浮动中的第1个离包含块边界最近的子元素,它们的margin双倍了,但item2item4却没有双倍,这表示说包含块中只有和浮动方向一致的第1个子元素才会触发双倍边距。

这就是IE6浮动双倍边距的全部吗?

答案当然不是,因为margin-topmargin-bottom也会双倍,你能想到是在什么场景下吗?think and try.

结语

知其然,知其所以然,是一件很Cool的事。