CSS Margin Collapse
Tags: beginners, css
Published: 2019-11-05 20:34:07

---
title: CSS Margin Collapse
published: true
description: A beginners introduction to CSS Margin Collapse
tags: beginners, css
series: FrontEnd Development Zero to Hero 
---

Margin collapse is one of the tricky things about margins in CSS and it's a _foundational concept_ in understanding the CSS Box model. Not knowing when a margin collapse, can be a point of frustration and when they do you just have to deal with it. This post will attempt to introduce and treat this concept in a beginner-friendly approach with code snippets and images from the browser _Developer Tools_.

From the [previous post](https://dev.to/ziizium/the-css-box-model-14k), we learned that the `margin` property applies to _block level element_ and it's a shorthand for four other properties:

* `margin-top`
*  `margin-right`
* `margin-bottom`
* `margin-left`

Now, when the `margin-top` and `margin-bottom` of this element _combine into a single margin_  whose size is the _largest of the individual margins_ (or just one of them, if they are equal). This behavior is known as _margin collapsing_ and it usually occurs in three  cases:

* Adjacent siblings
* No content separating parent and descendants
* Empty blocks

####__ADJACENT SIBLINGS__
From the [Mozilla Developer Network]( https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing) (emphasis mine): 
> The __margins of adjacent siblings are collapsed__ (except when the latter sibling needs to be cleared past floats).

__This translates to__:  If you have one or more block-level elements appearing one after the other from the top of the page i.e vertically, their margin will collapse.

Let's explain with code. 

_Don't forget to create your HTML and CSS files to follow along, and remember all HTML snippets will be in the `body` tag._

Given the code snippet below:

```html
<div class="parent">
  <div class="child"></div>
  <div class="child two"></div>
</div>
```
```css
/* cosmetics*/
.parent {
  margin-top: 32px;
  margin-right: auto;
  margin-left: auto;
  margin-bottom: 32px;
  background-color: rgb(200,200,200);
  width: 500px;
}

/*
 * The real deal is the margin-bottom value, the rest
 * are cosmetics.
*/
.child {
  margin-top: 30px;
  margin-right: 20px;
  margin-bottom: 50px;
  margin-left: 20px;
  width: 100px;
  height: 100px;
  background-color: #1560bd;
}

.child.two {
  margin-top: 20px;
  background-color: red;
}
```

From the snippet above, the `margin-bottom` of the child element is `50px` and we gave the adjacent box a `margin-top` of `20px`. Normal intuition will tell you that these values should add up since they are block-level element's and the space between `.child` and `.child.two` should be `70px`, but that's not the case.

Save your files and load the HTML in your browser, Use "Inspect Element" on the _blue box_, Navigate to the __Layout__ tab and click on the _Box Model_, you will realize that the space between the _blue box_ and the _red box_ is still `50px` even though the  _red box_ has a `margin-top` value of `20px`, the browser did not take this value into consideration. When something like this happens, _the margin is said to have collapsed_.

![Margin Collapse in CSS](https://thepracticaldev.s3.amazonaws.com/i/bw90utx4jfekg1y4tflr.PNG)

But what happens _if we have one negative margin value_? This will cause a slight deviation in the behavior of margin collapsing and _the positive and negative margins will be added together_ to reach the final margin.

This means if our _blue box_ has a `margin-bottom` of `50px` and the _red box_ has a ` margin-top` of `-20px`, the browser will calculate the margin between them as:

* _50 + (-20)_ => _50 - 20_ => _30_

The value gotten from the above calculation will be the space between the boxes.

Change the `margin-top` of the `.child.two` CSS rule (the red box) to a negative value:

```css
.child.two {
  margin-top: -20px; /* Add this */
  background-color: red;
}
```

Save your CSS file, and refresh your browser. The _red box_ will now move up a little bit and will _occupy part of the bottom margin of the blue box_.

![Margin Collapse in CSS](https://thepracticaldev.s3.amazonaws.com/i/rvbf670vhza1ubxx66l3.PNG)

####__NO CONTENT SEPARATING PARENT AND DESCENDANT__
The title says it all, but [Mozilla Developer Network]( https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing) has more:

> If there is no border, padding, inline part, block formatting context created, or clearance to separate the `margin-top` of a block from the `margin-top` of one or more of its descendant blocks; or no border, padding, inline content, height, `min-height`, or `max-height` to separate the `margin-bottom` of a block from the `margin-bottom` of one or more of its descendant blocks, then those margins collapse. The collapsed margin ends up outside the parent.

Update your CSS and HTML with the code below:

```html
<h1>This is the header</h1>
<div class="parent">
  <p class="child">Lorem ipsum dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
```
```css
.parent {
  margin-top: 50px;
  margin-right: 0;
  margin-bottom: 25px;
  margin-left: 0;
  outline: 5px solid red;
}

.child {
  margin-top: 20px;
  margin-right: 0;
  margin-bottom: 0;
  margin-left: 0;
  background: #1560bd;
  color: #ffffff;
}
```
Save your files and refresh your browser, you will notice that the browser did not render the `margin-top` property of the child element because the `.parent` has a higher `margin-top` value of `50px`, but _the browser knows the `margin-top` value of the child_. How? Perform the following steps:

* Use "Inspect element" on the paragraph
* Navigate to the __Layout__ tab
* Click on the _Box Model_

You will notice that the browser actually recognized the `20px`.

![Margin Collapse in CSS](https://thepracticaldev.s3.amazonaws.com/i/flnq7o1s62c0fqgepie6.PNG)

And if you hover your mouse (or pointing device) over the _margin value_ in the box model, the browser will highlight (in yellow) where the margin should have occupied in the web page, but, the margin is not rendered because it collapsed with the parent margin.

![Margin Collapse in CSS](https://thepracticaldev.s3.amazonaws.com/i/o65co5yfvda5dngdb6u0.PNG)

####__EMPTY BLOCKS__
Empty blocks are block level element with no content. And If there is no `border`, `padding`, inline content, `height`, or `min-height` to separate these block's `margin-top` from its `margin-bottom`, then its _top and bottom margins collapse_.

Update your CSS and HTML to match the following snippet.

```html
<div class="box"></div>
```
```css
.box {
  background: red;
  width: 120px;
  margin-top: 20px;
  margin-bottom: 50px;
}
```

Save your files and refresh your browser. Use the Developer Tools to view the _Box Model_, hover your mouse over the _yellow area_ of the _Box Model_ you will notice that the _margin bottom is not rendered_ but the browser acknowledge its value in the box model (highlighted in the image).

![Margin Collapse in CSS](https://thepracticaldev.s3.amazonaws.com/i/hlj1zgpq3nekd44ta205.PNG)

However, if you give the empty block a `height` or `min-height`, it will not collapse.

```css
.box {
  background: red;
  width: 120px;
  margin-top: 20px;
  height: 120px; /* Add this */
  margin-bottom: 50px;
}
```

![Margin Collapse in CSS](https://thepracticaldev.s3.amazonaws.com/i/oa4ndj2pmmizcq2h7n6p.PNG)

The question now is _How can we stop margins from collapsing?_

#####__PREVENTING MARGIN COLLAPSE__
From previous explanation we can realize that only consecutive elements can collapse into each other. Putting an element with a non-zero height between our elements forces them to display their margins. This element can be a _border_ or a _padding_.

Let's demonstrate.

Refer to the code snippet under _NO CONTENT SEPARATING PARENT AND DESCENDANT_, add a border declaration to the CSS `.parent` rule:

```css
.parent {
  margin-top: 50px;
  margin-right: 0;
  margin-bottom: 25px;
  margin-left: 0;
  outline: 5px solid red;
  border-top: 1px solid #000; /*Add this*/
}
```

Save your file and refresh your browser. The margin will now take effect.

![Preventing Margin Collapse](https://thepracticaldev.s3.amazonaws.com/i/dn0knz3mmakneo8097dm.PNG)

Now delete the border declaration you just added to the `.parent` CSS rule, and add the following to your HTML just before the paragraph with the `.child` class:

```html
<div style='padding-top: 1px'></div>
```

Save your file and refresh your browser, if you've done everything right you will get the same result similar to when you applied a border with CSS.

Another way to _avoid margin collapsing_ is to consider _applying only top margin_ or _bottom margin_ to elements

_Note that the margins of_ __floating__ and __absolutely positioned elements never collapse__.

Speaking of _Positioning_. That's Next.