Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird behavior related to float and margin

Tags:

html

css

position

The problem is the position of the div with the .parent class. It is not at the top of the window, but is 100px below, which is exactly the value of margin-bottom of .child.

Can anybody explain what is happening here?

Here is my HTML document:

<html>
    <head>
        <style>
            .parent {
            }
            .child {
                margin-bottom:100px;
            }
            button {
                float:left;
                height:30px;
            }
        </style>
    </head>
    <body>
        <div class="parent">
            <div class="child">
                <button>click me!</button>
            </div>
        </div>
    </body>
</html>
like image 366
Ling Yang Avatar asked Sep 21 '15 00:09

Ling Yang


1 Answers

That's caused by incompletely handling floats and not mastering Margin Collapsing

Margin Collapsing on Empty blocks
If there is no border, padding, inline content, height, or min-height to separate a block's margin-top from its margin-bottom, then its top and bottom margins collapse.

You need to get rid of floated elements issues using overflow:auto; on the parent or
by clearing your floats i.e: using a class:

.clear:before,
.clear:after{
    content: " ";
    display: table;
}
.clear:after{
    clear: both;
}

NB: Using background colors will help you to target such issues in the future:

"A parent has no visible background-color?" 99% a float issue!

Collapsing margins Issue:

.parent {
  background: red;
}
.child {
  background: gold;
  margin-bottom:100px;
}
button {
  float:left;
  height:30px;
}
<div class="parent">
      <div class="child">
        <button>Left floated Button</button>
      </div>
</div>

we have Collapsing Margins since .child has no (non-floated) Content or any set height to add-to it's box model so button collapsed to the nearest available space - floating left.
By just adding height: 1px; or just a text character inside .child you'll see the collapsing issue "fixed".

Clearing floats

using our .clear (or overflow:auto;) on the parent:

.parent {
  background: red;
}
.child {
  background: gold;
  margin-bottom:100px;
}
button {
  float:left;
  height:30px;
}

.clear:before,
.clear:after{
  content: " ";
  display: table;
}
.clear:after{
  clear: both;
}
<div class="parent clear">
  <div class="child">
    <button>Left floated Button</button>
  </div>
</div>

you can see that the .parent added context/content thanks to the .clear hack creating a wrap for the .child and the floated button. Parent is now only aware of the .child 100px margin cause .child still has the collapsed margins issue.

Still no visible child's gold background? = We need to apply .clear (or again overflow) to it too!

.parent {
  background: red;
}
.child {
  background: gold;
  margin-bottom:100px;
}
button {
  float:left;
  height:30px;
}

.clear:before,
.clear:after{
  content: " ";
  display: table;
}
.clear:after{
  clear: both;
}
<div class="parent clear">
  <div class="child clear">
    <button>Left floated Button</button>
  </div>
</div>

So, to recap what was happening:

  • the .parent and .child could not handle the floated element therefore losing "height" collapsing to nothing since no other Content is present.
  • You can now imagine two thin elements (with no height) holding a floated button with .child being the only adding some 100px space with margin-bottom and pushing the floated element underneath that space (since floated) causing Collapsed Margins on empty blocks
  • → by just adding any fixed height to .child you'd see the floated element hop in the right place (at the child's top) since the new available space and un-collapsed margins.

Here's a good article about floats and related issues caused by floated elements

like image 128
Roko C. Buljan Avatar answered Nov 15 '22 05:11

Roko C. Buljan