添加额外标记

少年,还记得当年页脚的 <br clear="all" /> 吗?最早、也是W3C推荐的方法,简单明了,缺点就是要添加额外的标记。

<br style="clear:both"/>

浮动父元素(Float (Nearly) Everything,FNE)

显然,浮动父元素会影响到其他元素,一不做二不休,干脆把所有布局元素都浮动了,然后使用适当的元素(一般是页脚)进行清理。都浮动?你喜欢吗?反正我不喜欢。
参考:Clearing Floats: The FnE Method

对浮动元素的父容器应用overflow: autooverflow: hidden

原理

当元素overflow属性的值为non-visible(即不是overflow:visible,而是autohiddenscroll之一),其高度以子元素为基准。CSS 2.1是这样描述的(鄙人愚钝,愣是没看懂):

In addition, if the element has any floating descendants whose bottom margin edge is below the bottom, then the height is increased to include those edges. Only floats that are children of the element itself or of descendants in the normal flow are taken into account, e.g., floats inside absolutely positioned descendants or other floats are not.
对浮动元素的父容器应用overflow: non-visible,即可清除浮动。一般都是使用overflow: autooverflow: hidden,当然如果你的用户钟情于滚动条,使用overflow: scroll也可以。

如下图所示:

Clearing Floats with Overflow

overflow: non-visible还可以用来阻止内容环绕浮动元素。比如说我们在设计评论列表时,通常是将用户头像向左浮动、评论内容向右浮动,以避免评论内容环绕用户头像。现在只要对评论内容容器应用overflow:auto,无需再对评论容器设置浮动或者宽度。如果父容器设置overflow:non-visible属性,那对想要清除环绕的元素使用overflow: inherit也是可以的。

overflow-auto-2

<style type="text/css">
    .c { width: 400px;}
    .avatar {float: left;}
    .text {overflow: auto;}
</style>
<div class="c">
    <div class="avatar">
        <img src="http://www.w3.org/2008/site/images/identica-logo" />
    </div>
    <p class="text">Overflow:auto can also be used to prevent content from wrapping around the floated element. Let's
        say you are designing a comment list. You would, most likely, have an avatar floating on the left and the
        comment to the right. To prevent the comment from wrapping around the avatar just add overflow:hidden to the
        comment container. The advantage of using overflow here is that I don't have to set a float or width to the
        comment container. The container automatically aligns after the floated avatar image.</p>
</div>

缺点:

  • 使用overflow:auto后,当内容延伸到容器边界时容器将显示滚动条。例如长的不换行的文本(比如很长的url)或者比容器大的图片,都会使容器显示滚动条。
  • 为避免滚动条煞风景,你可能会考虑使用overflow:hidden替代。不过问题又来了,超出容器边界的内容将被隐藏。

解决方案(Demo

  • 对长文本强制换行
    .container {
    	word-wrap: break-word;
    }
  • 限制图像的最大宽度
    .container img {
        max-width: 100%;
        height: auto;
    }

3.3.搞定IE 6

IE 6是不吃overflow: non-visible这一套,还得额外加餐。
.container { _height:1%;}
* html .container { height:1%; }
.container {*zoom:1; }
随便用那一条都行,看个人习惯,更多信息可参考HasLayoutOn having layout

参考链接

4.clearfix

4.1.初始版本

源自How To Clear Floats Without Structural Markup
.clearfix:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}
.clearfix {
    zoom: 1;     /* IE < 8 triggers hasLayout */
}
存在问题:IE8以下垂直外边距不合并,其他浏览器上外边距合并。

4.2. perishablepress改进版

.clearfix:after {
  visibility: hidden;
  display: block;
  font-size: 0;
  content: " ";
  clear: both;
  height: 0;
}
.clearfix {*zoom: 1; } /* IE 5.5/6/7 */
存在问题:IE8以下垂直外边距不合并,其他浏览器上下外边距都合并。

4.3.Thierry Koblentz 改进版

统一为各种浏览器都不合并垂直外边距。
.clearfix:before,
.clearfix:after {
  content: ".";    
  display: block;    
  height: 0;    
  overflow: hidden;	
}
.clearfix:after {clear: both;}
.clearfix {*zoom: 1;}
关于三个版本的差异,可以查看这个Demo

4.4.参考文档

5.micro clearfix

基于Thierry Koblentz clearfix精简、改进。已知支持浏览器:Firefox 3.5+, Safari 4+, Chrome, Opera 9+, IE 6+
/**
 * For modern browsers
 * 1. The space content is one way to avoid an Opera bug when the
 *    contenteditable attribute is included anywhere else in the document.
 *    Otherwise it causes space to appear at the top and bottom of elements
 *    that are clearfixed.
 * 2. The use of `table` rather than `block` is only necessary if using
 *    `:before` to contain the top-margins of child elements.
 */
.cf:before,
.cf:after {
    content: " "; /* 1 */
    display: table; /* 2 */
}
.cf:after {
    clear: both;
}
/**
 * For IE 6/7 only
 * Include this rule to trigger hasLayout and contain floats.
 */
.cf {
    *zoom: 1;
}
micro clearfix生成伪元素并将其display属性设置为table,以创建一个匿名表单元格(anonymous table-cell)及新的块级格式化环境(block formatting context),:before伪元素阻止上外边距合并,:after伪元素用来清除浮动。无需再隐藏生成内容,所需代码的减少。

:before选择符无需清除浮动,而是用来阻止现代浏览器中上外边距合并。这样做有两个好处:

  1. 和其他创建新block formatting context的浮动清除技术保持一致,如overflow:hidden
  2. 与应用了zoom:1的IE 6/7保持一致
使用时注意content:" "中的空格,以避免Opera bug:如果HTML某处使用了contenteditable,清除浮动元素的周围会生成空格。另一个可选的修复方法是添加 font:0/0 a

来看一下Bootstrap中的应用:

.clearfix {
  *zoom: 1;
}

.clearfix:before,
.clearfix:after {
  display: table;
  line-height: 0;
  content: "";
}

.clearfix:after {
  clear: both;
}

content:""没有空格,不过多了一行line-height:0,应该是同样的考虑。

HTML5 Boilerplate 也在使用这一浮动清除方法。

老版本Firefox

Firefox < 3.5需要添加visibility:hidden来隐藏插入的字符,因为有时老版本的Firefox要用content:"."来避免body和第一个子元素之间产生间隔(例如 jsfiddle.net/necolas/K538S/)。

对于老版本Firefox可以使用其他浮动清除方法替代,如对容器元素应用overflow:hidden 或者 display:inline-block

总结

条条大道通罗马。前端开发中达成目标的方法很多,关键是选择适合项目的。就清除浮动的方法而言,不能拘泥于使用某种,选择一种作为常用方法的同时,还应根据实际情况配合其他方法使用,不然就容易钻牛角尖。没有一种方法是无懈可击的,在特定的环境中可能是出现意想不到的问题,这时就可以考虑使用别的替代方案了。

Update

2015.07.03: contain-floats

W3C 添加了一个新的值来清除浮动,但是目前还没有浏览器支持。

.container {
  min-height: contain-floats;
}