Elements are the building blocks of web pages–when building websites, you’re actually “laying bricks” of elements. When these elements are laid, you make use of CSS to tweak their appearance and their placement.
To properly place an element on a web page in relation to other elements we make use of things like padding and margins. These are:
- Padding: the space between the element border and the content area.
- Margin: the spaces between an element’s border and that of its neighbouring elements
Here’s how the padding and margin of an element are visualized using Google Chrome’s Web Inspector:
This should be clear enough, but there is a situation where the margin between one element and that of a neighbor will merge (or collapse) into a unified space; such that there is no way to properly tell whose space it is:
This might have happened in your own code if you have been writing HTML and CSS for a while. And it can be a thorn in your side if you have no idea what is happening behind the scenes!
To properly understand it, we need to start with what it means for margins to collapse.
What is a Collapsible Margin?
Good question, glad you asked. According to W3C:
“In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.“ – W3C
Let us take the words apart bit by bit.
So “adjoining margins” are margins that are next to each other, and they can combine to form a single margin. But does this mean that all adjoining margins are collapsible? The answer is no!
In CSS, adjoining margins are vertical margins that meet some rules. Yes, you read that correctly! It means that horizontal margins (margin-left
and margin-right
) are not considered adjoining margins. Additionally, there are some situations where vertical margins aren’t considered adjoining.
Let’s begin with some scenarios where collapsible margins do happen.
1. Parent Element and First Child
In the code sample below:
<div>Outside the parent</div> <div class="parent"> <p class="child"> Here is a paragraph housed in the parent element </p> </div>
The second div
is the parent and it contains a child p
. If we apply a margin-top
property to the parent and first child, causing both margins to touch, the margins will be collapsed.
div { background: #3d8bb1 /* blue */; } .parent { margin-top: 30px; background: #49b293 /* green */; height: 150px; } .child { margin-top: 10px; background: #b03532 /* red */; }
You might expect a margin to show directly above the red p
element, giving us a slice of green above it.
However, the parent and its child are aligned at their top edge, then the margin with the larger value is chosen (30px
) to appear them both, and the smaller one is collapsed to 0
. If the child had the larger value (say, 50px
) then that would be chosen to be the margin above them.
If you measure it, you’ll see that the space between the child’s border and the outside div
is 30px
.
Negative Margin Values
If both margins were to have negative values, like this:
.parent { margin-top: -30px; background: #49b293 /* green */; height: 150px; } .child { margin-top: -10px; background: #b03532 /* red */; }
The chosen margin is again the largest, which in this case is -10px
.
However, if one margin is a negative value and the other, we combine both values:
.parent { margin-top: 10px; background: #49b293 /* green */; height: 150px; } .child { margin-top: -30px; background: #b03532 /* red */; }
In this case, the margins will be added, which will give us a result of -20px
.
Important: values are determined in this exact same way in all scenarios where margins collapse.
2. Parent Element and Last Child
As you might imagine, collapsible margins can also happen between the margin-bottom
of a parent element and the margin-bottom
of a child element. Suppose we have HTML that looks like this:
<div class="parent"> <p class="child"> Here is a paragraph housed in the parent element </p> </div> <div>Outside the parent</div>
And styles that looks like this:
.parent { margin-bottom: 30px; background: #49b293 /* green */; height: auto; } .child { margin-bottom: 10px; background: #b03532 /* red */; height: 100px; }
The margin-bottom
with the larger value will be used, while the other will be collapsed to 0
. The difference here is that the height of the parent has to be set to auto
.
3. Adjacent Elements
Within a parent element, collapsible margins will happen when the first child element has margin-bottom
applied to it, and the next element has margin-top
applied to it:
<div class="parent"> <p class="first-child"> Here is a paragraph housed in the parent element </p> <p class="second-child"> This is the second child </p> </div>
If we apply margin-top
and margin-bottom
like this:
.first-child { margin-bottom: 30px; background: #b03532 /* red */; height: 150px; } .second-child { margin-top: 20px; background: #da6f2b /* orange */; height: 100px; }
In the same way we calculated before, the space between the border of the child elements will be 30px
, not 20px
.
3 Points to Remember About Collapsing Margins
That brings us to the end of this introduction to collapsing margins in CSS! In addition to what we have seen above, there are some important things I should reiterate regarding the value of a collapsed margin.
1. Block Level Elements
Collapsible margins are only possible when using block-level elements.
2. Margins Only Collapse Vertically
Only vertically adjoining margins will collapse, and even then not always.
2. Padding, Borders, and Clearance
If we added padding, border, or clearance to the elements in the above examples, the collapsing will not be applied. In other words, one way of getting rid of collapsible margin behavior is to add some sort of separation (border, padding, or clearance) between the margins.
Conclusion
While collapsing margins might sometimes be a pain, understanding how and where they take effect is very helpful, especially if you encounter them accidentally!
Learn More CSS Basics
-
CSSUnderstanding CSS Inheritance (Inherit, Initial, Unset, and Revert)
-
CSSHow to Use New CSS “:is()” for Easy Element Targeting
-
CSSDemystifying CSS Pseudo-Classes (:nth-child vs. :nth-of-type)
-
CSS7 CSS Units You Might Not Know About
No comments:
Post a Comment