Why does adding a border to a parent div change its size to contain the margin of its children but not when it doesn't have border?

21 views Asked by At

.parent {
  background-color: red;
  width: 100px;
  /* border: solid 5px black; */
}

.child {
  margin-top: 50px;
  width: 100px;
  height: 100px;
  background-color: green;
}
<html>
  <head></head>
  <body>
    <div class="parent">
      <div class="child"></div>
    </div>
  </body>
</html>

.parent {
  background-color: red;
  width: 100px;
  border: solid 5px black;
}

.child {
  margin-top: 50px;
  width: 100px;
  height: 100px;
  background-color: green;
}
<html>
  <head></head>
  <body>
    <div class="parent">
      <div class="child"></div>
    </div>
  </body>
</html>

The only one single thing that changes in the code in the first and second examples are the border that is applied to the parent div. How come it only contains the margin of the child when the border is applied?

1

There are 1 answers

0
Adrian On

Apparently, this behavior has a name and is called "margin collapsing".

According to this MDN article:

No content separating parent and descendants

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, or min-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.

Empty blocks

If there is no border, padding, inline content, height, or min-height to separate a block's margin-top from its margin-bottom, then its top and bottom margins collapse.

Some things to note:

  • ...
  • Margins don't collapse in a container with display set to flex or grid.

One simple solution would be to change the display of the parent div to flex with column direction, like so:

.parent {
  display: flex;
  flex-direction: column;
  background-color: red;
  width: 100px;
  /* border: solid 5px black; */
}

.child {
  margin-top: 50px;
  width: 100px;
  height: 100px;
  background-color: green;
}
<html>
  <head></head>
  <body>
    <div class="parent">
      <div class="child"></div>
    </div>
  </body>
</html>