闭合浮动

本文介绍闭合浮动,和对比两种“利用伪元素闭合浮动”的方案。

提示:本文章内容最后修改时间为2017年04月,部分内容可能已经过时

本文部分内容参考 那些年我们一起清除过的浮动 ,但是 这位作者 的这篇文章有很多地方我都不认同,取其精华去其糟粕,所以本文并没有包含那些我所不认同的内容。

区分 清除浮动 和 闭合浮动

  • 清除浮动:对应CSS中的属性是 clear:left | right | both | none;
  • 闭合浮动:解决因为子元素浮动导致父元素高度塌陷的问题

两者的区别 请看Demo

闭合浮动的一些老方法:

  • 利用局部的“最后的元素”的“清除浮动”
    • 【1】在子元素们的最后追加一个style="clear:both"的空标签,这个不好
    • 【2】在子元素们的最后追加一个br标签,使用br标签的clear="all | left | right | none" 属性,因为一般不建议在HTML中使用br标签,这个也不好
  • bfc 作为布局上下文
    • 【3】通过设置父元素overflow值设置为hidden;在IE6中还需要触发 hasLayout ,例如 zoom:1;因为最终还是有补不了的bug被大家弃用
    • 【4】通过设置父元素overflow值设置为auto,同样也有bug
    • 【5】父元素也设置浮动,缺点是使得与父元素相邻的元素的布局会受到影响,不可能一直浮动到body,不推荐使用
    • 【6】父元素设置display:table,盒模型属性已经改变,由此造成的一系列问题,得不偿失,不推荐使用。文章最后还会再介绍到给父元素的伪元素设置display:table
  • 利用伪元素after作为“最后的元素”的“清除浮动” 【如下文】

7. 使用:after伪元素

需要注意的是 :after是伪元素,不是伪类(另外,某些CSS手册里面称之为“伪对象”,不太对)。

由于IE6-7不支持:after,要同时使用 zoom:1触发IE6和IE7的 hasLayout。在后面的demo中会介绍到。

  • 优点:浏览器支持好,不容易出现怪问题(目前:大型网站都有使用,如:腾迅,网易,新浪等等)

不要使用方案3和4

方案3、4通过overflow闭合浮动,实际上已经创建了新的 块级格式化上下文,而它们设置的对象都是父元素,这将导致其布局和相对于浮动的行为等发生一系列的变化,闭合浮动只不过是一系列变化中的一个作用而已。所以为了闭合浮动去改变全局特性,这是不明智的,带来的风险就是一系列的bug,比如firefox 早期版本产生 focus,截断绝对定位的层等等。始终要明白,如果单单只是需要闭合浮动,overflow就不要使用,而不是某些文章所说的“慎用”。

父级div定义height的方法 #不灵活

  • 父级div定义height,这样就不必闭合浮动
  • 不推荐使用,只建议高度固定的布局时使用

小结

通过对比,我们不难发现,其实以上列举的方法,无非有两类:

其一,通过在浮动元素的末尾添加一个空的元素

其二,通过设置父元素 overflow 或者display:table 属性来闭合浮动,原理就是BFC,下面探讨一下:

其三,「利用伪元素after作为“最后的元素”的“清除浮动”」之后再讲。

深入理解伪元素闭合浮动

上面已经列举了7种闭合浮动的方法,通过第三节分析的原理,我们发现其实更多的:对父元素使用display:table-cell,display:inline-block等只要触发了BFC的属性值都可以闭合浮动。

从各个方面比较,方案7:after伪元素闭合浮动无疑是相对比较好的解决方案了。这种思路的演进历史可以参考文章:https://css-tricks.com/snippets/css/clear-fix/

而最后,方案7里面有两个最值得一提的“具体方案”:

具体方案1: #仅供对比参考效果、理解debug;相对地不常用

这种也是比较多人用的写法之一,但是流行程度相对地不如另一个写法。

.clearfix:before,
.clearfix:after {
content:"."; display:block; height:0; visibility:hidden; clear:both; }

.clearfix { *zoom:1; }

1)通过 content:"."生成内容作为伪元素的内容

2)display:block 使生成的元素以块级元素显示,占满剩余空间;

3)height:0 避免生成内容破坏原有布局的高度。

4)visibility:hidden 使生成的内容不可见,并允许可能被生成内容盖住的内容可以进行点击和交互;

5)同时要使用 zoom:1触发IE6和IE7的 hasLayout

通过分析发现,除了clear:both用来清除浮动的,其他代码无非都是为了隐藏掉content生成的内容,这也就是其他版本的闭合浮动为什么会有font-size:0,line-height:0的缘故。

更重要的是,我认为这个方法根本就没产生 BFC 。

另外,不建议将content设置为空字符串"",在firefox 7里面会看到它会产生空隙

最优具体方案2: #这种最为常用

.clearfix:before,
.clearfix:after {
    content: " "; /* 1 */
    display: table; /* 2 */
}

.clearfix:after {
    clear: both;
}

.clearfix {
    *zoom: 1;
}

1. 使用content: " " 是为了避免Opera的bug,否则它会在 被清除浮动的元素的顶部和底部 产生一个看得出的空格

2. 这里对伪元素使用的display: table;会产生一个 anonymous boxes 和一个BFC,这个BFC意味着before伪类会阻止上外边距的合并,同时after伪类会闭合浮动。

需要注意的是,display:table 本身并不会创建BFC,但是它会产生匿名框(anonymous boxes),而匿名框中的display:table-cell可以创建新的BFC,换句话说,触发块级格式化上下文的是匿名框,而不是display:table。所以通过display:table和display:table-cell创建的BFC效果是不一样的。

**这个具体方案的好处是:**不用隐藏用content属性产生的内容,并且代码量特别少。

设置before伪元素的作用:间接产生BFC,以阻止上外边距合并,显得上下对称

设定before伪元素的属性并不是用来闭合浮动的,不过它能阻止上外边距的合并, 这会带来两个好处:

  • 这种清除浮动的方式所表现出来的外貌看上去和 其他的清除浮动的方式(比如overflow:hidden)的 一致。
  • 和IE6/7使用zoom:1后的外貌保持一致

毕竟,使用after伪元素闭合浮动的时候,下外边距的合并已经被阻止了,为了上下看上去对称,before伪元素也应该这样。

主要译自: A new micro clearfix hack

文章目录
  1. 区分 清除浮动 和 闭合浮动
  2. 闭合浮动的一些老方法:
    1. 7. 使用:after伪元素
    2. 不要使用方案3和4
    3. 父级div定义height的方法 #不灵活
  3. 小结
  4. 深入理解伪元素闭合浮动
    1. 具体方案1: #仅供对比参考效果、理解debug;相对地不常用
    2. 最优具体方案2: #这种最为常用
      1. 设置before伪元素的作用:间接产生BFC,以阻止上外边距合并,显得上下对称