A bit more about margins
Of all the box model properties, margins have a few unique features, which is why they get an extra lesson.
- The
<body>has a margin of8pxfrom the user agent styles. - We can use
automargins to center things - Margins can collapse into one another.
The default margin
Section titled “The default margin”We’ll start with the easiest one of all. In most projects, one of the first lines of code you’ll probably write is this:
body { margin: 0;}Horizontally centering block elements
Section titled “Horizontally centering block elements”We can use margin-inline: auto to horizontally center block elements.
An auto margin on the top and bottom will compute to 0, but on the left and right, the browser will distribute the space to center the element.
Collapsing margins
Section titled “Collapsing margins”The concept of margins is pretty simple: They add empty space between elements.
In reality, they cause a lot of frustration for many developers.
There are a few sane strategies for dealing with them, but before we worry about those, we need to tackle the potentially confusing parts in how they work.
We’ve seen how they can get in the way in the project we’re working on, moving things around in what seems like strange ways, and or adding extra space to places that we aren’t expecting it.
In normal flow, block elements’ block margins will “collapse” (the top and bottom margins).
I understand the idea of going with the term “collapsing”, but I prefer to explain it as the margins merging.
The concept here is a bit odd, but thanks to so many block elements having margin on the top and bottom by default, this prevents double spacing between them.
The collapsing of margins between adjacent elements isn’t an intuitive behaviour, but once you know about it, it isn’t hard to deal with it, and in many ways, it allows for more robust typographic patterns:
If this were the only way that margins collapsed, it wouldn’t be an issue, but there’s a bit more to it.
A child’s margin can collapse with its parent’s margin
Section titled “A child’s margin can collapse with its parent’s margin”A common situation where I see people run into this issue is when they have an element with a background, and inside of that element, there is another element that they want to move down.
Anytime the margins on the block axis touch one another, whether adjacent or child elements, those margins will “collapse”, causing them to act as one single margin.
We can stop the child’s margins from touching the parent’s one by adding a border or some padding, which creates a separation, which means they no longer collapse. Because of this, I’ve seen plenty of people add 1px of padding, or a 1px transparent border to elements… it works, but there are better solutions, which we will get to soon.
When margins don’t collapse
Section titled “When margins don’t collapse”There are a surprising number of situations where collapsing margins no longer collapse:
- First, margins only collapse on the block-axis, never in the inline-axis.
- If an element establishes a new formatting context, its margins will not collapse with those of its children.
- The margins of grid and flex items do not collapse.
These exceptions to how they collapse can make this behaviour more annoying because in some situations margins collapse, and in others, they don’t!
Generally speaking, we can say that in normal flow (so by default) margins collapse, but when we make a change to a new context (like a new display type), we can generally expect them to no longer collapse.
Strategies for dealing with collapsing margins
Section titled “Strategies for dealing with collapsing margins”To start with, we’ll address the more annoying part where a child’s margins collapse with it’s parent’s margins.
The solution is simple: Use padding on the parent instead of margin on the child.
There are other solutions that range from hacky to “okay, that works”, but 99.9% of the time in situations like this, people want more background.
More background = padding.
This creates too much space
Section titled “This creates too much space”The eagle-eyed of you out there might have realized that this can quickly result in much more space than you wanted!
We often want space between siblings, but we don’t normally want extra space on the top of the first element or the bottom of the last element.
Collapsing margins are one of those things that we get used to dealing with when we understand what is going on, but if we take certain approaches to dealing with margins in general, we don’t often run into issues with them.
Removing the unwanted margin
Section titled “Removing the unwanted margin”There are a few strategies for dealing with unwanted margins. One is to remove all of them from the block axis, and then re-introduce them where needed.
* { margin: 0;}Others will use this approach, but only in areas where it’s needed.
.element-with-padding > * { margin-block: 0;}.element-with-padding > p { margin-block: 1em;}And finally, we can be a little more precise.
.element-with-padding > :first-child { margin-block-start: 0;}
.element-with-padding > :last-child { margin-block-end: 0;}Alternative methods
Section titled “Alternative methods”There are more advanced ways of dealing with this, where you remove the margin from all elements and then create a utility class that re-introduce them in each place you need them.
I don’t think you need to dive into that approach early on in your journey, but I do explore that in my Build a Website from Scratch course here on Frontend Masters.