CSS: clean solution to the margin collapse issue w

2019-01-14 02:14发布

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 to margin: -1px 0 0 0; border-top: 1px solid;.
  • insert <div style="height: 1px; margin-bottom: -1px;"></div> before first
  • insert the above <div> between the first and second

Is there a clean, idiomatic way of avoiding this issue?

7条回答
叼着烟拽天下
2楼-- · 2019-01-14 02:55

Another trick that you can use when overflow:hidden is not suitable:

.clr:before, .clr:after {
    display: table;
    content: " ";
    clear: both;
    font-size: 0;
}

This snippet has the side-effect of containing all floats as well.

查看更多
走好不送
3楼-- · 2019-01-14 02:59

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.

查看更多
对你真心纯属浪费
4楼-- · 2019-01-14 02:59

Add float: left; to the second div.

fiddle

查看更多
家丑人穷心不美
5楼-- · 2019-01-14 03:02

The W3C specs describes this about collapsing margins:

"In this specification, the expression collapsing margins means that adjoining margins (no non-empty content, padding, or border areas, or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin."

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:

#element-with-collapsed-margin {
   padding-top:1px;
}

or border-top would fix this as well

#element-with-collapsed-margin {
   border-top:1px solid transparent;
}

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

..

查看更多
手持菜刀,她持情操
6楼-- · 2019-01-14 03:03

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

<html>
  <body style="padding: 0; margin: 0;">
    <div style="border: 1px solid black">
        <div style="float: right;">first</div>
        <div style="margin-top: 2em;">second</div>
    </div>
  </body>
</html>
查看更多
劳资没心,怎么记你
7楼-- · 2019-01-14 03:09

SOLUTION

add overflow: auto; or overflow: hidden; or overflow: scroll; to both html and body 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 to body?

Here is why:

W3C#block-formatting

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

W3C#overflow:

UAs must apply the 'overflow' property set on the root element to the viewport.

When the root element is an HTML "HTML" element or an XHTML "html" element, and that element has an HTML "BODY" element or an XHTML "body" element as a child, user agents must instead apply the 'overflow' property from the first such child element to the viewport, if the value on the root element is 'visible'.

The 'visible' value when used for the viewport must be interpreted as 'auto'.

The element from which the value is propagated must have a used value for 'overflow' of 'visible'.

the first such child element and The element from which the value is propagated refer to body tag in this case.

In other words, if you add overflow: hidden; or overflow: auto; or overflow: scroll; to body while the value of html's overflow property is visible, the value of body's overflow property(hidden or auto or scroll) 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; or overflow: auto; or overflow: scroll; to html, the overflow value of 'body' would not be propagated and hence establish new block formatting context.

查看更多
登录 后发表回答