Margin collapse is something that mentioned in every CSS book’s first or second chapter. When I learned about the stylesheets in a long time ago, of course, I read about it. These memories a little bit wore out so its time to refresh my knowledge, let’s start it!
Margin collapsing is that when two or more margin value – vertically, top or bottom – adjoining into one. These margins have to relate – or connect – to each other in some way.
Mainly this was needed because of the paragraphs and the others typography related elements. If you use both the top and bottom margin you don’t have to think about the exact values – the sum of both – because if two margins meet the bigger will win.
The usefulness of this is self-evident. If you want to set a margin to 30px, you don’t want the next element also add its own 30px to it. Thus it will collapse and will be 30px the spacing between these because each has a 30px margin alone.
Multiple Margins
So far to this point, it is bright like the sky; understanding the margin collapsing start to be more complicated when we arrive at the parent-children relation (and the exceptions in the next block).
Beforehand I mentioned the multiple – more than two in this case – values. The collapsing also works when you have an extra wrapper element inside it with a component which also has margin.
Having a parent div can cause some unexpected result because your inside element – with margin – overflow outside of it’s parent boundaries. Apparently, the first and the last child element will be problematic.
In our demo case we have two paragraph – the second in the div – and one div element. The .second-paragraph has a 20px margin-bottom, the .third-paragraph has a 60px margin-top and the div has zero – the zero margin also plays – margin-top value and the 60px value will win and specify this part’s margin value. The math is simple, the bigger beats, the smaller.
See the Pen Margin Collapse Demo – Generic by Adam Laki (@adamlaki) on CodePen.
Margins Don’t Collapse When
There are cases where we want to control or disable the margin collapsing; mostly this is actual when you have a parent-children relation:
- In case of margin-top if there has any padding, border, inline part, block formatting context or clearance between the parent element’s margin and the first-child element’s margin.
- In case of margin-bottom if there has any padding, border, inline element, or height (height, min-height, max-height) between the parent and the last-child element.
- Using display: flex; declaration on the container the children element’s margin doesn’t collapse too.
- Declaring overflow: auto; (works with every value except visible) on the parent prevents collapsing too.
- Display elements with table-cell or table-row value will not collapse because these elements don’t have a margin.
See the Pen Margin Collapse Demo – Disable Collapsing by Adam Laki (@adamlaki) on CodePen.
In case of empty element, the collapse won’t work if it has padding, border, inline content, height or min-height which separate the items.
In case adjacent siblings the collapsing not working when the latter element clear a float.
Using Negative Margins
We can also have collapse margins with negative values. If you have a positive (100px) and a negative (-50px) value than the margin will be the positive – negative: 100px + (-50px) = 50px.
See the Pen Margin Collapse Demo – Negative Margin by Adam Laki (@adamlaki) on CodePen.
If you have two negative values than the more significant negative (not that which is closer to zero) will win like -100px and -50px will be -100px.
Useful Link(s)
- For more info about the block formatting context navigate to MDN.