1

I'm using the trick from https://stackoverflow.com/a/6615994 to get a div where the height will equal the percentage width. The structure looks like this :

#container {
  display: block;
  width: 200px;
  height: 200px;
  position: relative;
  border: 2px dashed blue; /* just for demo */
}

#icon-container {
  width: 25%;
  position: relative;
  display: block;
  
  /* Removing the border property causes #icon-container to have 0 height */
  border: 2px dashed red;
}

.icon-spacer {
  /* margin-top calculated based on width of parent */
  margin-top: 100%;
}

.icon {
  /* My content will be displayed as a background-image in this element */
  background-color: black;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
<div id="container">
  <div id="icon-container">
    <div class="icon-spacer"></div>
    <div class="icon"></div>
  </div>
</div>

While I was testing this, I ran into the following behavior : if I remove the "border" CSS from #icon-container , then it gets a height of 0. This can be seen in the snippet here and on the fiddle here : https://jsfiddle.net/s2b4xr1a/2/

Since my real app is not going to have that border, how can I get the div to show up and have the correct height based on its children ? Also, why does this happen ?

Community
  • 1
  • 1
Julien Zakaib
  • 196
  • 10

2 Answers2

1

It's a margin collapse problem. The border keeps the margin on .icon-spacer within #icon-container-border, giving that element height. Without the border, the margin on .icon-spacer collapses outside of the parent.

Michael Coker
  • 52,626
  • 5
  • 64
  • 64
1

This has to do with CSS collapsing margins, which cause vertical margins between two or more boxes to combine and form a single margin.

Except, vertical margins do not collapse if there is a border or padding between the boxes. So, if you want to keep the effect in your layout, but need to remove the borders, add 1px of padding.

Add if you have height / width settings that need to be preserved, add box-sizing: border-box, which will factor padding (and border, btw) in to height / width calculations.

#container {
  display: block;
  width: 100%;
  position: relative;
  border: 2px dashed blue;
}

#icon-container-border {
  width: 25%;
  position: relative;
  display: block;
  
  /* Removing the border property causes #icon-container to have 0 height */
  /* border: 2px dashed red; */
  
  padding: 1px; /* NEW */
}

* {
  box-sizing: border-box; /* NEW */
}

#icon-container-no-border {
  width: 35%;
  /* Different width than first just to show that 1:1 ratio of width and height is preserved */
  position: relative;
  display: block;
  /* If border is added here, second div will show up as well, but why ?? */
  /* border: 2px dashed red; */
}

.icon-spacer {
  /* margin-top calculated based on width of parent */
  margin-top: 100%;
}

.icon {
  background-color: black;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
<div id="container">
  <div id="icon-container-border">
    <div class="icon-spacer"></div>
    <div class="icon"></div>
  </div>
  <div id="icon-container-no-border">
    <div class="icon-spacer"></div>
    <div class="icon"></div>
  </div>
</div>

revised fiddle

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701