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?
Another trick that you can use when
overflow:hidden
is not suitable:This snippet has the side-effect of containing all floats as well.
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.Add
float: left;
to the second div.fiddle
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
..
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
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.