闭合浮动元素

2006.04.2118:33

按照CSS规范,浮动元素(floats)会被移出文档流,不会影响到块状盒子的布局而只会影响内联盒子(通常是文本)的排列。因此当其高度超出包含容器时,一般父容器不会自动伸长以闭合浮动元素。但是有时我们却需要这种自动闭合行为,具体如何处理呢?

闭合浮动元素示意图

有一种做法就是在父容器内再插入一个额外的标签,并令其清除浮动(clear)以撑大父容器。这种方法浏览器兼容性好,没有什么问题,缺点就是需要额外的(而且通常是无语义的)标签,所以我个人不大喜欢。后来又有了一种新的方式,使用 :after 伪类动态的嵌入一个用于清除浮动的元素,这种方法和上一种原理一样,不同的只是把这个额外的内容用 CSS 生成,但考虑到 IE 不支持 :after 不得不做了不少的 hack。这种方法兼容性一般,但经过各种 hack 也可以应付不同浏览器了,同时又可以保证 html 比较干净,所以用得还是比较多的。再后来又有人发现将父容器的 overflow 设为除 visible 之外的值就可以在标准兼容浏览器中闭合浮动元素,IE自然又是不支持的,所以这种方法和上一种方法一样都对 IE 做了不同处理(具体就是触发layout),不同的就是overflow 没有 :after 伪类那么麻烦了,缺点也有,overflow 可能会产生一些小冲突。在使用 overflow 之前还有过一种使用 float 的方法,就是让父容器也浮动,这利用到了浮动元素的一个特性——浮动元素会闭合浮动元素。这种方式在 IE/Win 和标准兼容浏览器中都有较好的效果,但缺点也很明显——父容器未必想浮动就浮动的了,毕竟浮动是一种比较特殊的行为,有时布局不允许其浮动也很正常。使用 float 虽然在 IE 和标准兼容浏览器中都能闭合浮动元素,但原理却是不同的,IE/Win 中 float 触发了 layout 因而闭合了浮动,而在标准兼容浏览器中,float 其实和上一种方法中的 overflow 原理一样,产生了一个“块级格式化范围”——这是CSS 规范中提到的一种现象,它往往具有某种独立性,特性之一就是会自动闭合内部的浮动元素。

按照规范,以下类型的元素会产生一个块级格式化范围:

  • 浮动元素,left 或者 right 皆可。
  • 绝对定位的元素。
  • inline-block 元素,不过这个 gecko目前不支持。
  • table-cell 类型元素,其实 table, table-head-group, table-row 什么的也都可以,还有inline-table(gecko不支持)也同样,因为他们都会间接产生一个匿名的 table-cell。
  • overflow 取值非 visible 的元素。

所以,原来在标准兼容浏览器中我们也可以有这么多的方法闭合一个浮动元素,而且只需要 CSS,无需其他。顺带说一下以上除了overflow,其余都有一个附加效果就是自动收缩父容器宽度。

而对于 IE/Win,它有一套自己的体系,就是 layout,具有 layout 的元素会自动闭合浮动元素,再来看看触发 layout 的 CSS 属性,会发现和上面的块级格式化范围有很多类似之处:

  • 浮动元素
  • 绝对定位元素
  • display:inline-block
  • zoom
  • width/height
  • overflow/overflow-x/overflow-y [IE7 新增]
  • max/min-width/height [IE7 新增]

以上来看 IE 中闭合浮动元素的方法也不少,自然也都有其局限性,要么有附带效果,要么使用的是非标准属性(无法通过验证)。

还要提一点的是 display:inline-block,这个属性对 IE 而言本身没什么用,实际效果只是给一个元素暗地添加了 layout,但是标准兼容浏览器是认得这个属性的,所以要不影响这些浏览器,需要将 display 设回默认。这里 IE 有一个 bug,如果先定义了 display:inline-block,然后再将 display 设回 block(这两个 display 要先后放在两个 CSS 声明中才有效果),那么 layout 不会消失,同时也不会影响其他浏览器,所以目前来说,这也算一个不错的触发 layout 的方法:

.gainlayout{display:inline-block;}
.gainlayout{display:block;}

所以要跨浏览器闭合浮动元素,可以选择的方式还是很多的,如何搭配使用这些 CSS 属性就要具体情况具体分析了,灵活应用条件注释也很有必要,要是实在不行我们回过头来还有 clear 可以用嘛。

10 Comments Comment RSS »

The URI to TrackBack this entry is: http://old9.blogsome.com/2006/04/21/enclosing-floats/trackback/

  1. 闭合浮动元素,我的习惯就是给它的父元素加上一句display:table;把它当作块元素级的表格显示 。

    Comment by 原始 — 2006.4.22 @ 16:46

  2. 嗯,display:table可以在标准兼容浏览器下有效,正如文中提到的,它间接产生了一个匿名的table-cell。但是IE就不认这个了,它只认layout。

    Comment by old9 — 2006.4.22 @ 16:54

  3. 请问一下,什么叫作关合浮动元素?---我是一初学者,请赐教。

    Comment by 丫子 — 2006.4.25 @ 11:36

  4. 嗯。。等下我来放两张图片示意一下吧。

    Comment by old9 — 2006.4.25 @ 19:00

  5. 最小高度100%,页脚保持在底部的布局方法

    有时候,我们用CSS创建一个高度自适应布局,如何保证页脚(footer)在内容不超过一屏的情况下始终保持在布局最下方是一个比较头疼的事。我看过一些利用绝对定位的例子,但总感觉不是那…

    Trackback by 踩 IE — 2006.5.11 @ 10:50

  6. overflow:auto;的基础上再加上_height:1%;就可以闭合浮动了,我今天看到的,可能已经过时了。
    完整代码
    #wrap{overflow:auto;_height:1%;}
    我测试了一下,发现这样做会给非IE带来一些问题,外围容器会多出一块来。区别对待才行。

    #wrap{overflow:auto;}
    * html #wrap{_height:1%;}

    Comment by greengnn — 2006.7.12 @ 22:10

  7. 很是郁闷,自己代码写差了,丢掉东西了所以错误显示。
    还是它吧!
    #wrap{overflow:auto;_height:1%;}

    Comment by greengnn — 2006.7.12 @ 22:35

  8. 嗯,overflow: auto; 给标准兼容浏览器建立了块级格式化范围,给 IE7 触发了layout,_heigth 给 IE6-/win 触发了layout。
    所以道理都是一样的,:)

    Comment by old9 — 2006.7.13 @ 08:13

  9. 不知道你们怎么想的,插入标签clear:both清楚浮动没有什么不好的,用hack反而是没有必要,当以后浏览器版本升级后,hack还得改,得不偿失;css里面加入hack,个人才认为是最无聊的做法

    Comment by 浩海扬帆 — 2006.9.30 @ 16:50

  10. 首先文中提到的标准兼容浏览器的闭合方法都不是 hack,而是严格按照 CSS 规范来显示的正确效果。

    而对于 IE,所有的的方法目的就是一个——让其具有 layout。至于怎么让它有 layout,用 hack 还是条件注释还是别的都可以,这个看各人习惯了,不是本文的重点。本文只是试图分析标准下和 IE 下闭合浮动的内部原理,而不是要给出一个最好的闭合方法。

    而你说的插入额外的标签 clear:both 来清除浮动的确是浏览器兼容最好的方法,文中也有提到,但是由于需要嵌入额外的标签,这对于某些十分重视 html 文档语义化的人(比如我和这里的一些其他朋友)来说,是不大理想的。

    Comment by old9 — 2006.10.01 @ 19:42

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>


为防评论机器人,劳驾您输入图片中的字符 :)
captcha