CSS:浮动元素时边距折叠问题的干净解决方案
HTML+CSS 示例:
<html>
<body style="padding: 0; margin: 0;">
<div style="float: right;">first</div>
<div style="margin-top: 2em;">second</div>
</body>
</html>
所需行为:first
div 浮动到窗口的右上角。 实际行为:它浮动在所需位置下方 2em 处。 原因: 边距折叠。
尽管确定了问题,但我能想出的解决方案感觉就像黑客:
- 将
body
样式更改为margin: -1px 0 0 0;顶部边框:1px 实线;
。 - 在
first
之前插入 - 插入上面的
<
first
和second
之间的 div>
是否有一种干净、惯用的方法来避免此问题?
Example HTML+CSS:
<html>
<body style="padding: 0; margin: 0;">
<div style="float: right;">first</div>
<div style="margin-top: 2em;">second</div>
</body>
</html>
Desired behavior: the first
div floats to the top-right of the window. Actual behavior: it floats 2em below the desired position. Reason: margin collapsing.
Despite identifying the problem, the solutions I can come up with feel like hacks:
- change
body
style tomargin: -1px 0 0 0; border-top: 1px solid;
. - insert
<div style="height: 1px; margin-bottom: -1px;"></div>
beforefirst
- insert the above
<div>
between thefirst
andsecond
Is there a clean, idiomatic way of avoiding this issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
将
overflow: hide;
添加到body
应该可以解决您的问题。它定义了一个新的块格式化上下文,如本文所述:溢出的魔力:隐藏。jsFiddle Demo (
body
标签是由 jsFiddle 自动添加的,这就是为什么我没有' t 将其包含在 HTML 标记中)更新(感谢 @clairesuzy):如果
body
具有padding: 0
,则此解决方案不起作用。在我找到更好的方法之前,我只能建议在两个 div 周围添加一个包装器(至少我现在应该得到 @Marcel 的 downwote :)),我仍然认为这比 OP 发布的解决方案更干净。我通常会在浮动内容周围添加一个包装器(在大多数情况下更容易处理旧浏览器),大多数情况下不需要故意添加,因为它在逻辑和语义上都是必需的。所以现在,我可以想出这个:
jsFiddle 演示
更新 2 :经过深思熟虑并阅读评论后,我确实认为容器上的
overflow:hidden
(或overflow:visible
以外的任何内容)是正确的解决方案。它对我不起作用的唯一例外是将其设置在body
元素上,无论如何,这是一种非常罕见的情况。在这些罕见的情况下,您可以尝试使用position:absolute;顶部:0; right: 0;
而不是浮动。另一种可能的解决方法:我还发现设置
display: inline-block; width: 100%;
在body
上确实有效。jsFiddle 演示
Adding
overflow: hidden;
to thebody
should solve your problem. It defines a new block formatting context as described in this article: The magic of overflow: hidden.jsFiddle Demo (the
body
tag is automatically added by jsFiddle, that's why I haven't included it in the HTML markup)UPDATE (thx to @clairesuzy): This solution does not work if
body
haspadding: 0
. Until I can find a better way, I can only suggest to add a wrapper around the two divs (at least I deserve now @Marcel's downwote :)), which I still think is cleaner than the solutions posted by the OP. I normally add a wrapper around floated stuff anyways (makes it easier to handle older browsers most of the time), most of the time it does not need to be added deliberately, because it is logically and semantically required.So for now, I can come up with this:
jsFiddle Demo
UPDATE 2: After thinking it through, and reading comments, I really think that
overflow: hidden
(or anything other thanoverflow: visible
) on the container is the right solution. The only exception where it did not work for me is setting it on thebody
element, which is a very rare situation anyways. In these rare situations, you can try usingposition: absolute; top: 0; right: 0;
instead of floating.Another possible workaround: I have also found that setting
display: inline-block; width: 100%;
onbody
works indeed.jsFiddle Demo
在父
div
上添加此#parent {padding 1px 0; }
这对我来说是一个大问题,我花了很长时间才找到解决方案。我在一篇帖子上看到了大约 2 年,这修复了崩溃。On the parent
div
add this#parent {padding 1px 0; }
this was a huge issue for me and it took me for ever to find a solution. I saw on a post like 2 years and this fixes the collapse.解决方案
将
overflow: auto;
或overflow:hidden;
或overflow:scroll;
添加到html
和>body
标签。如果您想知道为什么
在
body
标记上创建块格式上下文 (BFC)。为什么如果我仅将
overflow: hide;
添加到body
则不起作用?原因如下:
W3C#block-formatting
W3C#overflow:
在本例中,
第一个此类子元素
和传播值的元素
引用body
标记。换句话说,如果您将
overflow:hidden;
或overflow: auto;
或overflow:scroll;
添加到body
> 当html
的overflow
属性的值为visible
时,body
的属性的值为
属性(visible
溢出隐藏
或auto
或scroll
)将传播到视口。因此,根据第一个 W3C 引用,body
不会建立新的块格式化上下文。但是,如果您将
overflow:hidden;
或overflow: auto;
或overflow:scroll;
添加到html
, “body”的溢出值不会被传播,因此会建立新的块格式化上下文。SOLUTION
add
overflow: auto;
oroverflow: hidden;
oroverflow: scroll;
to bothhtml
andbody
tag.IF YOU WANT TO KNOW WHY
Creating block formatting context(BFC) on
body
tag.Why it does not work if I add
overflow: hidden;
only tobody
?Here is why:
W3C#block-formatting
W3C#overflow:
the first such child element
andThe element from which the value is propagated
refer tobody
tag in this case.In other words, if you add
overflow: hidden;
oroverflow: auto;
oroverflow: scroll;
tobody
while the value ofhtml
'soverflow
property isvisible
, the value ofbody
'soverflow
property(hidden
orauto
orscroll
) will be propagated to the viewport. So according to the first W3C quote,body
would not establish new block formatting context.However, if you add
overflow: hidden;
oroverflow: auto;
oroverflow: scroll;
tohtml
, theoverflow
value of 'body' would not be propagated and hence establish new block formatting context.将
float: left;
添加到第二个 div。小提琴
Add
float: left;
to the second div.fiddle
W3C 规范描述了有关折叠边距的内容:
http://www.w3.org/TR/CSS21/box.html #collapsing-margins
处理折叠边距的最佳方法是仅向具有折叠边距的元素的顶部或底部填充添加一个像素。
如果边距折叠在顶部..那么:
或 border-top 也可以解决这个问题,
如果你的底部边距折叠,那么你将添加 padding-bottom:1px;或 border-top:1px 实心透明;
基本上,当您将它们放在另一个之上时,或者甚至当您将元素嵌套在彼此内部时,顶部或底部的任何边框或填充都会阻止边距折叠。边距折叠
很好的参考:
http://reference.sitepoint.com/css/collapsingmargins
..
The W3C specs describes this about collapsing margins:
http://www.w3.org/TR/CSS21/box.html#collapsing-margins
best way to deal with collapsing margins is to just add one pixel to the top or bottom padding of the element that has the collapsed margin.
if the margin was collapsing on top.. then:
or border-top would fix this as well
if your bottom margin is collapsed then you would add padding-bottom:1px; or border-top:1px solid transparent;
basically any border or padding on top or bottom will stop the margins from collapsing when you have they above one another or even when you have elements nested inside each other that have margin collapse
good reference:
http://reference.sitepoint.com/css/collapsingmargins
..
当
overflow:hidden
不合适时,您可以使用另一个技巧:此代码段还具有包含所有浮动的副作用。
Another trick that you can use when
overflow:hidden
is not suitable:This snippet has the side-effect of containing all floats as well.
这可能很奇怪,但在新版本的 Chrome 和 Mozilla 中,您可以通过添加带边框的包装 div 来实现所需的行为(第一个 div 位于右上角)
It might be strange but in new versions of Chrome and Mozilla you can achieve the desired behavior (first div is at the top right) by adding wrapper div with border
将
clear: right
添加到第二个秒add
clear: right
to second second