CSS: a pure solution to the problem with a field crash when moving an element

HTML + CSS example:

<html> <body style="padding: 0; margin: 0;"> <div style="float: right;">first</div> <div style="margin-top: 2em;">second</div> </body> </html> 

Desired behavior: div first floats in the upper right corner of the window. Actual behavior: it floats 2 mark below the desired position. Reason: margin reversal .

Despite identifying the problem, the solutions I can come up with look like hacks:

  • change the body style to margin: -1px 0 0 0; border-top: 1px solid; margin: -1px 0 0 0; border-top: 1px solid; .
  • insert <div style="height: 1px; margin-bottom: -1px;"></div> to first
  • insert above the <div> between first and second

Is there a clean, idiomatic way to avoid this problem?

+21
css margin layout css-float
Jun 01 '11 at 16:38 on
source share
7 answers

Adding overflow: hidden; in body should solve your problem. It defines a new context for block formatting, as described in this article: Overflow Magic: Hidden .

jsFiddle Demo (the body tag is automatically added by jsFiddle, so I did not include it in the HTML markup)

UPDATE (thanks to @clairesuzy): This solution does not work if body has padding: 0 . Until I can find a better way, I can only offer to add a wrapper around two divs (at least I deserve now @Marcel downwote :)), which, in my opinion, is cleaner than the solutions posted by the OP. I usually add a wrapper around floating material in any case (it simplifies the processing of older browsers most of the time), most of the time it does not need to be added intentionally, because it is logically and semantically required.

So now I can come up with this:

 <body style="padding: 0; margin: 0;"> <div id="container" style="overflow: hidden;"> <div style="float: right;">first</div> <div style="margin-top: 2em;">second</div> </div> </body> 

jsFiddle Demo

UPDATE 2 . After thinking about it and reading the comments, I really think that overflow: hidden (or anything other than overflow: visible ) on the container is the right solution. The only exception in which it did not work for me is to set it to the body element, which is very rare. In these rare situations, you can try using position: absolute; top: 0; right: 0; position: absolute; top: 0; right: 0; instead of swimming.

Another possible workaround: I also found that setting display: inline-block; width: 100%; display: inline-block; width: 100%; on body really works.

jsFiddle Demo

+22
Jun 01 2018-11-17T00:
source share

In the parent div add this #parent {padding 1px 0; } #parent {padding 1px 0; } , this was a huge problem for me, and it took forever to find a solution. I saw in the mail how 2 years, and this eliminates the collapse.

+2
Mar 02 '13 at 17:33
source share

Decision

add overflow: auto; or overflow: hidden; or overflow: scroll; in the html and body tags.

IF YOU WANT TO KNOW WHY

Creating a block formatting context (BFC) in the body tag.

Why this does not work if I add overflow: hidden; only to body ?

That's why:

W3C # block formatting

Floats, absolutely positioned elements, block containers (for example, built-in blocks, cell tables and table headers) that are not block blocks, and block blocks with an "overflow" other than "visible" ( excluding when this value was distributed in the window view ), create block formatting contexts for their contents.

W3C # overflow:

UAs must apply the overflow property in the root element to the viewport.

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

The β€œvisible” value used for the viewport should be interpreted as β€œauto”.

The element from which the value extends must have the value used to overflow the visible .

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

In other words, if you add overflow: hidden; or overflow: auto; or overflow: scroll; in the body , and the value of the html overflow property remains unchanged, the value of the body overflow hidden or auto or scroll property) will be passed to the viewport. Thus, according to the first W3C quote, body will not set a new block formatting context.

However, if you add overflow: hidden; or overflow: auto; or overflow: scroll; in html , the overflow 'body' value will not be propagated and therefore will create a new block formatting context.

+2
Jan 26 '16 at 9:08
source share

Add float: left; in the second div.

fiddle

+1
Jun 01 '11 at 16:51
source share

The W3C specs describe this about folding borders:

β€œIn this specification, expression discarding fields mean that adjacent fields (without non-empty content, filling or border areas or marking up their markup) from two or more boxes (which may be next to each other or nested) are combined to form a single stock.”

http://www.w3.org/TR/CSS21/box.html#collapsing-margins

The best way to deal with collapsing fields is to simply add one pixel to the top or bottom padding of an element that has a collapsed field.

if the edge was compressed from above .. then:

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

or border-top will also fix this.

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

if your bottom margin is minimized then you will add padding-bottom: 1px; or border-top: 1px solid transparent;

basically any border or padding above or below stops dropping fields when you have them above each other, or even when you have elements nested inside each other that have margin collapse

Good link:

http://reference.sitepoint.com/css/collapsingmargins

..

+1
Oct 19 '13 at 0:42
source share

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

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

This fragment has a side effect containing all the floats.

+1
Feb 24 '14 at 17:30
source share

This may be strange, but in the new versions of Chrome and Mozilla you can achieve the desired behavior (the first div is in the upper right corner) by adding a div shell with a 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> 
0
Apr 11 '17 at 6:46 on
source share



All Articles