This might be due to margin collapsing and I know about margin collapsing, at least how it affects adjacent elements, but I don’t understand how it works on nested elements when negative margins are involved.
For example, in this markup and accompanying CSS:
Markup
<div class="parent">
<div class="child">
Child 1
</div>
</div>
<div class="parent">
<div class="child negative">
Child 1
</div>
</div>
CSS
body {
background: white;
padding: 45px;
}
.parent {
border: 1px solid black;
margin-bottom: 10px;
}
.negative {
margin-bottom: -1px;
}
Live example here.
When I inspect the height of the second .parent div, I notice it is 1 pixel less than the first one. This has happened because of the negative margin on the .negative element inside it. I had a quick look at W3C and couldn’t find an explanation for this behavior.
Could someone please explain what’s happening here and also provide me with a link to the W3C spec section about it?
Section 8.3.1 has all the details. It also covers the behavior of adjoining margins between nested boxes, as well as negative margins.
However, what you’re seeing here is not the effect of margin collapse because you have negated it with a
border: 1px solid blackdeclaration in your.parentrule. That means having a border there prevents your.parentmargin from collapsing with your.child.negativemargin altogether.Rather, this is simply how negative margins work. This is covered in various sections of the visual formatting model, but it’s most succinctly and directly addressed in the beginning of Section 11, which summarizes it thus:
So what’s happening here, instead, is:
The absolute value of the
.child.negativeelement’s negative margin is subtracted from the.parentelement’s actual height (by1px).As a result, the
.child.negativeelement itself overflows.parent(because its own height is not changed and the defaultoverflowfor anydivisvisible).Since margin collapse does not take effect here, the
margin-bottom: 10pxin your.parentis unaffected. Note that while any subsequent elements in normal flow will be shifted up by1px, this is mainly due to the negative margin of your.child.negativeelement; in other words, a side effect of step 1.And that’s all there is to it.