如何防止浮动元素的父元素崩塌?

1066
< p >尽管像 < code > < div> 这样的元素通常会根据其内容自动扩展,但是使用< code > float 属性可能会给 CSS 新手带来一个惊人的问题:< strong >如果浮动元素具有非浮动父元素,则父元素将折叠。

例如:

<div>
  <div style="float: left;">Div 1</div>
  <div style="float: left;">Div 2</div>
</div>

在这个例子中,父元素div不会展开以包含其浮动的子元素-它将显示为height: 0

如何解决这个问题?

我想在这里创建一个详尽的解决方案列表。如果您了解跨浏览器兼容性问题,请指出。

解决方案1

将父元素设置为浮动。

<div style="float: left;">
  <div style="float: left;">Div 1</div>
  <div style="float: left;">Div 2</div>
</div>

优点: 语义化的代码。 缺点: 您可能并不总是希望父元素浮动。即使您确实想要,您是否需要漂浮父母的父母,以此类推?必须漂浮每个祖先元素吗?

解决方案2

给父元素设置明确的高度。

<div style="height: 300px;">
  <div style="float: left;">Div 1</div>
  <div style="float: left;">Div 2</div>
</div>

优点: 语义化的代码。
缺点: 不够灵活——如果内容更改或浏览器大小调整,则布局将破裂。

解决方案3

在父元素内部添加一个“spacer”元素,像这样:

<div>
  <div style="float: left;">Div 1</div>
  <div style="float: left;">Div 2</div>
  <div class="spacer" style="clear: both;"></div>
</div>

优点: 编码简单明了。
缺点: 不语义化;占位符div仅作为布局技巧存在。

解决方案4

将父元素设置为overflow: auto

<div style="overflow: auto;">
  <div style="float: left;">Div 1</div>
  <div style="float: left;">Div 2</div>
</div>

优点:不需要额外的div。
缺点:看起来像一个hack - 这不是overflow属性的官方目的。

有其他评论或建议吗?


38
我之前不知道 overflow:auto 的技巧,我一直使用清除浮动的 div 方法。谢谢你的提示。 - Herb Caudill
7
提示:解决方案4似乎适用于Firefox 3+,但不适用于IE7。对于IE7,您需要使用解决方案3。 - Manos Dilaverakis
9
根据这里所述的情况(http://stackoverflow.com/questions/11830433/overflowauto-adding-scrollbars-in-chrome-ie),`overflow:auto`似乎存在一些问题,会在不应该出现滚动条的地方添加滚动条,因此请改用`overflow:hidden`。 - Rodolfo
2
关于overflow属性,您可能会对我在以下问题的回答感兴趣:为什么overflow: hidden会出现意外的副作用,导致高度增加以包含浮动元素? - BoltClock
9
我赞成使用overflow: auto。这是唯一对我有效的选项。 - Chris Redford
显示剩余16条评论
15个回答

562

解决方案 1:

最可靠和不显眼的方法似乎是这样的:

演示: http://jsfiddle.net/SO_AMK/wXaEH/

HTML:

<div class="clearfix">
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>
</div>​

CSS:

.clearfix::after { 
   content: " ";
   display: block; 
   height: 0; 
   clear: both;
}

通过一点 CSS 的定位,你甚至不需要给父级 DIV 添加 class。

这个解决方案兼容 IE8,所以你不需要担心旧版浏览器的问题。

解决方案 2:

有人提出了解决方案 1 的改进版本,如下所示:

演示:http://jsfiddle.net/wXaEH/162/

HTML:

<div class="clearfix">
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>
</div>​

CSS

.clearfix::after { 
   content: " ";
   display: block; 
   height: 0; 
   clear: both;
   *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML += '<div class="ie7-clear"></div>' );
}

.ie7-clear {
    display: block;
    clear: both;
}

这个解决方案似乎向后兼容到IE5.5,但没有经过测试。

解决方案3:

也可以设置display: inline-block;width: 100%;来模拟普通块元素而不会折叠。

演示:http://jsfiddle.net/SO_AMK/ae5ey/

CSS:

.clearfix {
    display: inline-block;
    width: 100%;
}

这个解决方案应该向后兼容IE5.5,但只在IE6中进行了测试。


9
当元素设置了padding时,使用宽度为100%的内联块会产生不良影响。 在ie6中,:after选择器无效。 - lededje
15
IE6(甚至是IE7)存在一个损坏的浮动模型,无法完全通过任何类型的清除浮动解决。 - BoltClock
4
说真的,谁会关心IE6呢:D 如果是IE8我还能理解,但即使到了2012年,IE6也太过时了:P - Dany Khalife
1
我认为 content: " "; 可以改成 content: "";,这样会更加简洁。 - chenghuayang
6
@Davidtaubmann,W3Schools绝不是官方网站或标准的一部分,它们由第三方公司运营,与W3C无关。尽管它们在过去几年中有很大改进,但许多开发人员仍认为它们是信息来源不佳。我建议您通常查看MDN或Web Platform Docs(远不如W3Schools详尽,但官方)的文档。我省略了“overflow:auto”技巧,因为提问中已经提到了要寻求其他建议。 - A.M.K
显示剩余14条评论

81

通常我使用overflow: auto的小技巧;虽然这不是严格意义上的overflow的预期用途,但它与overflow有点关系 - 足以使人们轻松记住。在我看来,float: left本身的含义已经被扩展为各种更重要的用途,比起overflow在此示例中所占的作用。


恭喜,这正是官方w3解决方案:http://www.w3schools.com/css/tryit.asp?filename=trycss_layout_clearfix - DavidTaubmann
23
W3和W3Schools不是同一个东西,实际上,在标准HTML方面,我认为W3Schools托管了一些非常“可疑”的内容。 - D.R.
2
关于W3Schools,我认为它们在这些年里至少有所改善,但重要的是要意识到,就像@D.R.所说,它们并不是万维网联盟(W3C)。 - TecBrat

20

不要将overflow:auto放在父元素上,而应该使用overflow:hidden

我为任何网页编写的第一个CSS始终是:

div {
  overflow:hidden;
}

那么我就再也不必担心它了。


11
这是一个不好的想法。你不想随意裁剪任何东西,特别是如果你在那些div上设置了固定的尺寸。此外,有些情况下,overflow: autooverflow: hidden更可取(例如当内容溢出时你想让它可以滚动)。 - BoltClock
1
自从我发布了这个以后,我已经停止使用它作为全局默认值。我认为overflow:hidden通常是最好的解决方案。每种情况都不同。感谢您指出这一点 ;) - tybro0103
没问题 - 我想我还是会添加这个注释,以备将来需要的时候。 - BoltClock
副作用:https://dev59.com/zWcs5IYBdhLWcg3wgkWu?lq=1 - Griffin

18

当浮动元素位于容器框内时,容器框的高度不会自动调整以适应浮动元素,这就是问题所在。当一个元素被浮动后,其父元素不再包含它,因为浮动元素已经脱离了文档流。你可以使用以下两种方法来解决它:

  • { clear: both; }
  • clearfix

一旦你理解了发生了什么,使用下面的方法来“清除浮动”。

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

.clearfix {
    display: inline-block;
}

html[xmlns] .clearfix {
    display: block;
}

* html .clearfix {
    height: 1%;
}

演示 :)


我遇到了一个问题,就是在ie6中,浮点数会导致我的div边框崩溃。我添加了height: 0,这解决了ie6的问题,但破坏了ie7及以上版本。:( 后来发现,height: 1%可以解决ie6的问题,而不会破坏ie7及以上版本! :D - bloodyKnuckles

15

有几个版本的清除浮动,Nicolas GallagherThierry Koblentz是其中的主要作者。

如果您想要支持旧版浏览器,最好使用这个清除浮动:

.clearfix:before, .clearfix:after {
    content: "";
    display: table;
}

.clearfix:after {
    clear: both;
}

.clearfix {
    *zoom: 1;
}

在SCSS中,您应该使用以下技术:

%clearfix {
  &:before, &:after {
    content:" ";
    display:table;
  }

  &:after {
    clear:both;
  }

  & {
    *zoom:1;
  }
}

#clearfixedelement {
    @extend %clearfix;
}
如果你不关心旧浏览器的支持,那么有一个更短的版本:
.clearfix:after {
    content:"";
    display:table;
    clear:both;
}

9

虽然这段代码不是完全语义化的,但我认为在每个包含浮动元素的容器底部放置一个我称之为“清除div”的元素更加直观明了。事实上,我在每个项目的重置块中都包含了以下样式规则:

.clear 
{
   clear: both;
}
如果你在为IE6编写样式(上帝保佑你),你可能也需要将这个规则的行高和高度都设为0px。

如果你在元素内部有类似于Facebook“赞”框,你需要使用这种方法,否则当你点击“赞”时,Facebook评论框将被裁剪。 - Simon_Weaver

9
理想的解决方案是使用inline-block来代替浮动以实现列布局。如果你遵循以下两点,我认为浏览器支持还不错:(a) 只对通常为行内元素的元素(如)应用inline-block;(b) 对于Firefox,添加-moz-inline-box。请在Firefox2中检查页面,因为当嵌套某些元素时,我遇到了大量问题(出乎意料的是,在这种情况下,IE的表现比FF好得多)。

9

奇怪的是,还没有人为此提供完整的答案,啊哈,这里有。

解决方案一:clear: both

在块级元素上添加样式clear:both;将清除该点之后的浮动,并防止其父元素崩溃。http://jsfiddle.net/TVD2X/1/

优点:允许您清除一个元素和它下面的元素不受上面的浮动元素影响,且有效的 CSS。

缺点:需要另一个标签来清除浮动,臃肿的标记。

注意:要回退到 IE6 并使其在禁欲的父级(即输入元素)中工作,您无法使用:after。

解决方案二:display: table

在父元素上添加display:table;以使其摆脱浮动并以正确的高度显示。http://jsfiddle.net/h9GAZ/1/

优点:没有额外的标记,更加简洁。适用于IE6+。

缺点:需要无效的 CSS 以确保在 IE6 和 7 中一切正常。

注意:IE6 和 7 的宽度自动用于防止宽度为100%+填充,这在新的浏览器中不是这种情况。

其他“解决方案”的说明

这些修复程序适用于最低支持的浏览器,全球使用率超过1%(IE6),这意味着使用:after行不通。

溢出隐藏显示内容但不防止元素崩溃,因此无法回答问题。使用内联块可能会产生错误的结果,子元素具有奇怪的边距等,表格更好。

设置高度可以“防止”崩溃,但这不是一个正确的解决方案。

无效的 CSS

无效的 CSS 从未伤害任何人,事实上,现在已经成为规范。使用浏览器前缀与使用特定于浏览器的 hack 一样无效,对最终用户没有任何影响。

总之

我同时使用上述两种解决方案,使元素正确地反应并相互协调,我敦促您也这样做。


1
IE6 从什么时候开始支持 display: table - BoltClock
首先,上述的方法都经过了IE6的测试,而且它们都能正常工作。如果你提供一个不起作用的示例,再来找我。供应商特定的规则并不适用于不支持它们的浏览器(这就是供应商特定的意思...)。所以当然它们不会被处理...这就是重点,但它仍然允许你使用最新的CSS规则。 - lededje
1
“zoom” 从未出现在任何 CSS 规范中……它是由微软独自创建和使用的。 - BoltClock
display: table” 方案实际上是在我的情境下(在一个复杂的网站中注入 CSS 的 Chrome 扩展程序)唯一有效的解决方案。非常感谢! - cprcrack
-1 - andygoestohollywood
显示剩余6条评论

6
我在适用的情况下使用2和4(即当我知道内容的高度或溢出不会造成伤害时)。在其他任何地方,我采用第三种解决方案。顺便说一下,我无法发现你的第一个解决方案有任何优势,因为它并不更语义化,因为它使用相同的虚拟元素。 顺便说一下,我不会担心第四个解决方案是一个hack。在CSS中的hack只有在其基本行为受到重新解释或其他更改时才会有害。这样,您的hack不能保证起作用。但是在这种情况下,您的hack依赖于“overflow:auto”应具有的确切行为。没有坐享其成的伤害。

糟糕 - 我在第一个解决方案中删除了虚拟元素。那是个错误。感谢您指出。 - Nathan Long

5
我最喜欢的方法是为父元素使用clearfix类。
.clearfix:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}

.clearfix {
    display: inline-block;
}

* html .clearfix {
    height: 1%;
}

.clearfix {
    display: block;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,