杨的空间
业精于勤,荒于嬉,行成于思,毁于随

这篇文章是 Holly Bergevin 和我最初为CommunityMX 网站 写的,该网站资源丰富,论坛里高手云集,不过需要订阅。

如果用表格布局,Internet Explorer 的表现和别的浏览器并无二致。但是如果用 CSS 来定位时, IE 表现得相当怪异。其中之一就是他对浮动的处理方式。

IE 到底如何与众不同?

要理解浮动模型,首先要弄清当浮动元素后面紧跟有非浮动元素时的行为。如浮动理论所说,紧跟在浮动元素之后的区块元素会无视该浮动元素的存在,显示在与浮动元素完全相同的位置上。浮动元素蒙在区块元素之上,该区块元素(假设没有指定其宽度)将横跨整个浏览器的视区或所在的容器宽度。

为了使元素显示在浮动元素的旁边,浮动元素必须在这些元素的前面。如果浮动元素紧跟在非浮动元素之后,它将出现在这些非浮动元素的正下方

当这种情况出现时(浮动元素后面紧跟区块元素),W3C的标准中说,区块元素必须显示在容器的顶部。现代浏览器对此都能正确执行。如图所示:

浅棕色的 div 紧跟在顶部,前面的绿色浮动块蒙在它的上面。按照标准,以深蓝色条纹表示的的行不允许出现在浮动块的背后。

<div style="float:left; width:30%;">
浮动区块内容。
</div>

<p>段落</p>

浮动块和 div 的相互关系的图片 请留意,之后的区块元素会伸展到整个容器的宽度,浮动元素只是覆盖在其上面。 W3C 标准规定,每行(包括文本和图片)必须显示在段落内未被浮动元素遮住的区域。同样,现代浏览器也符合这个标准。

一切都很正常,但是如果为区块元素指定了 width (或 height),情况就大不一样了。一旦指定了尺寸,IE 处理浮动元素的方式就发生了巨大的变化。

错在哪里

我们不妨为区块元素指定 {width: 100%;} 。 在大多数的现代浏览器中,结果不会有什么变化,因为 "100%" 指的是整个容器的宽度。不幸的是 IE 可不这么想。

在 IE 中, {width: 100%;} 重新解释为 浮动元素侧面所剩余的宽度,而不是标准中所说的整个容器的宽度。此外, 如果左边有浮动元素,则区块元素从它的右面 开始显示,如果右面有浮动元素,则区块元素从它的左边开始显示。而标准规定,无论是否存在浮动元素, dvi 都应该从视区的最左边开始显示。

总之,任何紧跟在浮动元素后面的区块元素,如果指定了它的高度或宽度, 在 IE 中观看时就会成这样。下图就是 IE 的显示,请与上图标准所要求的效果对照。

<div style="float:left; width:30%;">
浮动区块内容。</div>

<p>段落</p>
 
<p style="width:100%;">Paragraph</p>

IE 浮动块和 div 的相互关系 还记得,浮动元素背后的文本行应该被移出来。如果浮动元素比区块元素高,很难看出 IE 中没有把浮动元素盖在区块元素之上。如果区块元素没有边框和背景色,更难以察觉到这个变化。

如果浮动元素不是图片,则在 IE 下,两个元素之间会有 3 个像素的间隙,不过这个 IE 独有的问题将另文讨论。

IE 本身也不一致

如果说有浮动元素存在时,IE 对已指定尺寸的段落的宽度计算有误的话,更为难以想象的是 只要没有浮动元素,它却将同一页面内的另一个段落的宽度计算成整个容器的宽度。

图中显示的是IE 中一个浮动元素之后紧接两个 {width:100%;} 的段落,唯一的区别就是第一个段落在浮动元素的旁边,而第二个却不。所以即使不考虑它的错误,我们也无法指望 IE 的行为前后一致。

确实令人心烦。如果宽度不是100%,或者用其他单位来指定区块的宽度,情况更为糟糕。

现实的问题

OK,假如一个新手想用浮动来实现两个分栏的布局,他想要的就是两个简单、分离的栏目直到页低,这不算过分吧。在 Netscape 4 下的一个可行方案是为左边的栏目指定 {float:left;} 的样式,后面的区块从浮动块的右边直落下去。

假定浮动块的样式为 {width:50%;} ,为了将两个分栏垂直对齐,并将边框和背景区分开来,他将非浮动的分栏的左边距(left margin)设置为 "60%",右边距大概为 "5%"。浮动分栏也有一个左边距,离开左边一些。该代码的确可以创建两个简洁的肩并肩的分栏(见图)。

<div style="float:left; width:50%; margin-left:5%;">
Content in float.
</div>

<p style="margin-left:60%; margin-right:5%;">
Paragraph
</p>

IE 中看到的两个分栏 在 IE 下没有问题。但通常情况下,新手会为区块元素指定一个宽度。不幸的是,只有将后面的段落的width 设定为 70%左右,才能在 IE 中看起来舒服一些。浮动分栏不但需要左边距,而且还要有右边距(或者为右边分栏指定一个左边距),将右边的分栏推开一些。

现在这个新手终于高兴地得到了两个分栏。怎么不会呢?这种效果很容易实现,他所见到的就是他想要的。 不过他高兴得太早了。

非 IE 浏览器中看到的两个分栏 如果在一个真正遵守标准的浏览器(不是IE)观看这个布局,区块元素(根据标准)会从视区的左边开始,并且宽度只有 70%,在右边留下了 30% 的空白。真是糟糕,如果区块元素仅比浮动元素宽一点,浮动区块旁边蓝色条纹所表示的文本就会被挤得更短。而浮动区块的左边距又使得文本变得更短。如此一来,这些极短的行就使行数增加,从而增加了区块元素的高度,文字就会显示在浮动元素的下方,填满这个总宽度为70%的分栏,完全破坏了在非IE浏览器下的外观。令人怀疑这就是微软的用意?

如果浮动元素和区块元素的宽度相同或者更宽,则文字根本不会显示在旁边,而是全部被推倒了浮动元素的下方。这根本不是所希望的结果。

IE6 的新变化

现在我们已经知道,IE 6甚至连这个糟糕的浮动模型也不再遵守了。所以我们以上所说的目前只针对IE 5.x/win 而不是 IE 6。IE6 和 IE5.x 一样,仍然错误地计算浮动区块旁边的段落起始位置,可是它正确地将 {width: 100%;} 看成是外部容器的整个宽度,这一点和其他遵守标准的浏览器一致。

让我们来设想一下。一个段落的宽度是100%,但是从一个浮动元素的后面开始。 100% 加上浮动元素的宽度会略大于容器的宽度!如果容器是 body 元素,就会出现水平滚动条。

可以肯定的是,如果有人没有在 IE 浏览器下设计种浮动布局(指定区块元素的宽度),而在 IE 下观看时这种布局很容易错乱,在我看来这并不奇怪。如果倒过来,情况反而会更糟。

运用浮动的一些建议

对紧跟在浮动元素后面的元素不要制定宽度或高度。当然这意味着如果想实现独立的分栏,必须为区块元素指定一个左边距。很不幸者这又带来了 IE 下另一个缺憾。还记得我以前提到过的IE中 "3个像素" 的 bug吗?就是它。

结论

人们很容易注意到区块模型问题,而且最后得以修正。但是这个问题也同样严重。没有迹象表明微软会关注它,甚至根本不愿承认这个问题。 何苦呢?实际上根本没有人知道这个问题!

采用 CSS 定位非常有利于减少下载时间、简化网站设计更新和改进站点的亲和力,但是作为最广泛使用的浏览器, Internet Explorer 使之变得非常困难。但愿这种违背标准的行为总有个尽头。


Holly 'n John   e-mail ©positioniseverything
最后更新:January 18, 2004
写于 July 21, 2003
中文翻译:onestab Jan 30, 2004

posted on 2005-12-13 15:44 阅读(1045) 评论(0)  编辑 收藏 引用 所属分类: WEB标准相关(DIV+CSS)
只有注册用户登录后才能发表评论。