To understand this you need to know the difference between a BFC (block formatting context) and IFC (inline formating context.
When having only block elements inside your container this one will create a BFC:
In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the 'margin' properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.
In this case, only the height and margin of the block element inside are considered to calculate the height of your container and you only have one empty element so the height is 0.
When having an inline-block
/inline
elements you will trigger the creation of an IFC and the story is different:
In an inline formatting context, boxes are laid out horizontally, one after the other, beginning at the top of a containing block. Horizontal margins, borders, and padding are respected between these boxes. The boxes may be aligned vertically in different ways: their bottoms or tops may be aligned, or the baselines of text within them may be aligned. The rectangular area that contains the boxes that form a line is called a line box.
The height of a line box is determined by the rules given in the section on line height calculations.
As you discovered, we will be dealing with line boxes and line-height
will be considered here to define the height of each line box (in your case you have only one)
Now, the difference between the inline
and inline-block
is about white space. In the case of inline
element you will end having an empty container because all the white space will collapse. More details here: https://www.w3.org/TR/2011/REC-CSS2-20110607/text.html#white-space-prop.
If you change the white space algorithm (and you add a space) you will get the same height as with the inline-block
element.
.container {
background-color: red;
margin:5px;
white-space:pre;
}
<div class="container"><div style="display: inline-block;"></div></div>
<div class="container"><div style="display: inline;"> </div></div>
In addition to white space, inline-block
are slightly different because:
Inline-level boxes that are not inline boxes (such as replaced inline-level elements, inline-block elements, and inline-table elements) are called atomic inline-level boxes because they participate in their inline formatting context as a single opaque box.
It's not trivial to understand but to use easy words you can see the inline-block
element as an element where the content inside doesn't interact with the outside world (considering white space, line break, etc) and even if an inline-block
is empty, we will have a line box
Here is a basic example to see the difference:
.container {
margin: 5px;
font-size:30px;
}
div {
outline:1px solid green;
}
<div class="container">
a<div style="display: inline-block;"> some text here </div> text here
</div>
<div class="container">
a<div style="display: inline;"> some text here </div> text here
</div>
<div class="container">
a<div style="display: inline-block;"> some text<br> here </div> text here
</div>
<div class="container">
a<div style="display: inline;"> some text<br> here </div> text here
</div>
The last case is when you have inline
/inline-block
and also block
element in your container. In this case we will trigger a BFC but we have to consider Anonymous block boxes where we place the inline elements.
if a block container box (such as that generated for the DIV above) has a block-level box inside it (such as the P above), then we force it to have only block-level boxes inside it.
Then you can see the anonymous block box as an IFC and you get a recursive definition. A BFC where you have different blocks and each one can either be a BFC or an IFC and so on.
Related question dealing with the height of inline and block element: How to determine height of content-box of a block and inline element