Update 2020: the below behavior is no more visible in the recent browsers
Let's start with the following situation:
html {
background: red;
}
body {
margin: 0;
min-height: 100vh;
background-color: green;
}
div {
min-height: 50px;
background-color: pink;
margin-bottom: 50px;
}
<div></div>
The body is defined with a min-height:100vh
and we have a scroll bar that allow us to see the html
. Here we are having a margin-collapsing, the margin of the div
is collapsed with the body margin and thus create this space after the body and the scroll bar.
If we refer to the specification we have this case:
Two margins are adjoining if and only if:
...
bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height
the div
is the last in-flow element and body
has height auto as we only specified min-height.
Now let's add more elements that may be affected by this margin and keep the rules of margin-collapsing. The only way to do this is to add floated elements to keep our div
always the last in-flow element.
Here is the new code:
html {
background: red;
}
body {
margin: 0;
min-height: 100vh;
background-color: green;
}
div {
min-height: 50px;
background-color: pink;
margin-bottom: 50px;
}
.l {
width:45%;
height:50px;
float:left;
margin:0;
}
.r {
width:45%;
height:50px;
float:right;
margin:0;
}
<div></div>
<div class="l"></div>
<div class="r"></div>
As we can clearly see, we still have margin collapsing (because of the scroll) AND the floated elements are also pushed down by the same amount of the margin.
So my question is: why such behavior?
My understanding of margin-collapsing is that at the end we will have only one margin applied somewhere. By adding new elements, I am expecting to have one of this two situations:
- Adding the floated elements will somehow cancel the margin-collapsing (this cannot be the case as we are not breaking any rule)
- The floating elements will not get affected by the margin as this one collapsed with body margin and thus moved/applied to the body. (This is a logic case for me)
In the specification I also found this complex statement:
Note that the positions of elements that have been collapsed through have no effect on the positions of the other elements with whose margins they are being collapsed; the top border edge position is only required for laying out descendants of these elements.
I understand from the above that the other elements get not affected by the margin-collapsing and thus keep their initial position which explain why the floated elements are pushed down. (I am not sure if this is the case by the way)
If this is the explanation then it's a bit confusing and illogical for me. I added one margin and I end up having two margins that are clearly visible?
So why such behavior? Or maybe I missed something in the specification and we are facing more than a simple margin-collapsing?
Important notice: Before answering, please note that I am not looking for a fix to this or how to avoid this. I know at least 5 ways to cancel margin-collapsing (padding, overflow, border, flexbox,etc..).I am looking to understand why such thing happen.
For the reference: this started by this question where @Alohci highlighted this in my answer and after few comments we both didn't get convinced