
CSS: Dealing with Margin Collapse
The Issue
So you’ve got two elements sitting atop each other, each with vertical margins. You would expect the margins to add together:
.thing { display: block; width: 100%; height: 200px; } .thing-upper { margin-bottom: 50px; } .thing-lower { margin-top: 30px; }
… so the space between them is expected to be 50 + 30 = 80 pixels. Except they’re not.
When two vertical margins meet, they usually collapse; i.e., in most cases, where the margins of two elements meet, only the larger value is preserved (or if equal, only a single value).
This is the normal flow of the box model, and there are specific cases governing this collapse (blocks with margins but no content, adjacent siblings, etc.).
Solution
Maddening before one knows what's going on, but it’s workable.
The simplest method is to stick with either top or bottom. I prefer margin-bottom, because I usually want to be consistent with how much room there is underneath something. I also often have to override a margin-top anyway (header tags, i’m looking at you).
Other Notes
• There is a -webkit-margin-after-collapse property which can be set to "separate", but of course non-Webkit browsers get no love.
• You can include an :after pseudo-element with display:table, but I like reserving my befores and afters for interesting things.
• Floats do not collapse vertical margins, but you must control width and clearance (width: 100%, clear: both).
• Negative margins are funny. If both margins are negative (who does this?), then they act as if positive, preserving the larger absolute value. If one margin is negative, the negative margin is subtracted from the positive.
• First and last child elements tend to have their vertical margins overridden by their parent, or even extend their margin outside the parent. You can muck about with the properties of the child (like its padding), which sort of "wakes it up" and allows the margins to be preserved. See MDN web docs for painstaking but succinct details.
More Subheader
Client Work. Nothing but the good stuff: