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

尽管像<div>这样的元素通常会增长以适应它们的内容,但使用float属性可能会给CSS新手带来惊人的问题:如果浮动元素具有非浮动父元素,则父元素将折叠。

例如:

<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

在父元素中附加一个“间隔”元素,如下所示:

<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。
缺点:看起来像是黑客攻击-这不是overflow属性的既定目的。

评论?其他建议?

318045 次浏览

我通常使用overflow: auto技巧;虽然严格来说,这不是溢出的预期用途,但它有点相关-当然足以让它很容易记住。float: left本身的含义已经扩展到各种用途,比在这个例子中的溢出更重要,IMO。

我在适用的情况下使用2和4(即当我知道内容的高度或溢出不会造成伤害时)。在其他任何地方,我都使用解决方案3。顺便说一句,你的第一个解决方案与3相比没有优势(我可以发现),因为它没有更多的语义,因为它使用了相同的虚拟元素。

顺便说一句,我不担心第四种解决方案是黑客攻击。CSS中的黑客只有在其底层行为受到重新解释或其他更改时才会有害。这样,你的黑客攻击就不能保证有效。然而,在这种情况下,你的黑客依赖于overflow: auto应该具有的确切行为。搭便车没有坏处。

虽然代码不是完美的语义,但我认为在每个包含浮点数的容器的底部有一个我称之为“清除div”的东西更直接。事实上,我在每个项目的重置块中都包含了以下样式规则:

.clear{clear: both;}

如果你正在为IE6设计样式(上帝帮助你),你可能想给这个规则一个0px的line-高度和高度。

理想的解决方案是对列使用inline-block而不是浮动。我认为浏览器支持非常好,如果您遵循(a)仅将inline-block应用于通常内联的元素(例如span);(b)为Firefox添加-moz-inline-box

在FF2中也检查你的页面,因为我在嵌套某些元素时遇到了很多问题(令人惊讶的是,这是IE表现比FF好得多的情况)。

不是把overflow:auto放在父节点上,而是把overflow:hidden放在父节点上

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

div {overflow:hidden;}

那我就永远不用担心了。

当浮动元素位于容器盒内时,该元素不会自动强制容器的高度调整以适应浮动元素时,会出现问题。当元素浮动时,其父元素不再包含它,因为该浮动已从流中删除。你可以使用2种方法来修复它:

  • { 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%;}

演示:)

最著名的解决方案之一是解决方案3的变体,它使用伪元素而不是非语义html元素。

事情是这样的…

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

将其放在样式表中,只需将类“cf”添加到包含浮点数的元素中即可。

我使用的是来自Nicolas Gallagher的另一个变体。

它做同样的事情,但它更短,看起来更整洁,也许用来完成另一件非常有用的事情-防止子元素的边距与它的父元素一起崩溃(但为此你确实需要其他东西-在这里阅读更多关于它的信息http://nicolasgallagher.com/micro-clearfix-hack/)。

.cf:after {content: " ";display: table;clear: float;}

解决方案1:

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

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

超文本标记语言

<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添加类。

此解决方案向下兼容IE8,因此您无需担心旧浏览器失败。

解决方案2:

有人建议对解决方案1进行调整,内容如下:

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

超文本标记语言

<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中进行了测试。

将overflow更改为autohidden的主要问题是,所有内容都可以使用鼠标中键滚动,并且用户可以搞乱整个站点布局。

奇怪的是,还没有人想出一个完整的答案,啊,这就是。

解决方案一:明确:两者

添加一个风格清晰的块元素:两者;将清除该点过去的浮点数并阻止该元素的父元素折叠。http://jsfiddle.net/TVD2X/1/

优点:允许您清除一个元素,您在下面添加的元素不会被上面的浮动元素和有效的css影响。

缺点:需要另一个标签来清除浮点数,膨胀标记。

注意:要回退到IE6并使其在禁欲父母(即输入元素)上工作,您不能使用:后。

解决方案二:显示:表格

在父级中添加show: table;以使其摆脱浮点数并以正确的高度显示。http://jsfiddle.net/h9GAZ/1/

优点:没有额外的标记,并且更整洁。适用于IE6+

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

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

关于其他“解决方案”的说明

这些修复工作回到最低支持的浏览器,全球使用率超过1%(IE6),这意味着使用:之后不会削减它。

溢出隐藏确实显示了内容,但不能防止元素折叠,因此不能回答问题。使用内联块可能会有错误的结果,孩子有奇怪的边距等等,表格要好得多。

设置高度确实“防止”了坍塌,但这不是一个适当的解决方案。

无效的css

无效的css永远不会伤害任何人,事实上,它现在是常态。使用浏览器前缀与使用浏览器特定的黑客一样无效,并且不会影响最终用户。

最后

我使用上述两种解决方案来使元素正确反应并很好地相互配合,我恳请你也这样做。

另一个我认为在语义上更正确的可能解决方案是将浮动的内部元素更改为“显示:内联”。这个例子以及我在看到这个页面时所做的工作都使用浮动div,其方式与使用跨度的方式完全相同。不要使用div,切换到跨度,或者如果你使用的是另一个默认为“显示:块”而不是“显示:内联”的元素,那么将其更改为“显示:内联”。我相信这是100%语义正确的解决方案。

解决方案1,浮动父级,本质上是更改要浮动的整个文档。

解决方案2,设置一个明确的高度,就像画一个盒子,然后说我想在这里放一张图片,也就是说,如果你正在做img标签,就用这个。

解决方案3,添加一个间隔来清除浮点数,就像在内容下方添加一条额外的行,并且也会弄乱周围的元素。如果您使用这种方法,您可能希望将div设置为高度:0px。

解决方案4,overflow: Auto,承认您不知道如何布局文档,并且承认您不知道该做什么。

我认为最好的方法是将clear:both设置为即将到来的元素。

原因如下:

1):after选择器在IE6/7中不受支持,FF3中存在错误,但是,
如果你只关心IE8+和FF3.5+清除:之后可能最适合你…

2)overflow应该做其他事情,所以这个黑客不够可靠。

作者注意:清除并没有什么可怕的……清除意味着跳过浮动字段。CLEAR从HTML3(谁知道,也许更长)http://www.w3.org/MarkUp/html3/deflists.html开始就和我们在一起,也许他们应该选择一个不同的名字,比如page: new,但这只是一个细节……

我最喜欢的方法是为父元素使用clearFix类

.clearfix:after {content: ".";display: block;height: 0;clear: both;visibility: hidden;}
.clearfix {display: inline-block;}
* html .clearfix {height: 1%;}
.clearfix {display: block;}

将此添加到底部的父div中

 <div style="clear:both"></div>

clear补丁有多个版本,其中尼古拉斯·加拉格尔Thierry Koblentz是关键作者。

如果你想支持旧的浏览器,最好使用这个clear补丁:

.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;}