Contrary to what is mentioned in the accepted answer, the behavior discussed here is not related to Block Formatting Context or the "block" aspect of the inline-block
value. It primarily concerns the "inline" component.
All inline-*
elements contribute to the Inline Formatting Context. This implies that they are placed within "line boxes" alongside text and other inline-level elements. The alignment of these elements and text is such that the height of each line box is calculated from the highest element's top to the lowest one's bottom.
By default, inline-level elements align with the baseline of their fonts (as seen in the first line of the example below). Even if the parent element lacks actual text, the baseline's position and the minimum line box height are computed as if there were text present (referred to as the element's "strut"). Consequently, there is always some space above the baseline for ascenders and diacritics and below it for descenders, as illustrated in the second line.
The complexity arises for inline-block
elements due to the overflow
property altering what constitutes the baseline for these elements (referenced in section 10.8.1 of the spec):
An 'inline-block' element's baseline is its last line box's baseline in normal flow, unless it lacks in-flow line boxes or has a computed 'overflow' value other than 'visible', in which case the baseline becomes the bottom margin edge.
Hence, even though the space below the baseline is always reserved technically, with the default overflow: visible
, the inline-block element positions itself such that its text's baseline aligns with the parent's baseline while its lower part extends beneath it. Though this setup often makes the inline-block the line's lowest element, obscuring space reserved for font descenders, adjusting the overflow
reveals this space entirely.
p {
margin: .5em;
font: 32px/1.5 serif;
color: #fff;
background: #888;
}
span {
display: inline-block;
font: 12px/1 sans-serif;
background: #fff;
color: #000;
padding: 2px;
border: 1px solid green;
}
.ovh {
overflow: hidden;
border-color: red;
}
<p>Text with image <img src="http://via.placeholder.com/30x15"> and <span>two</span> <span>inline-block</span>s</p>
<p><img src="http://via.placeholder.com/30x15"> <span>only</span> <span>inline-blocks</span></p>
<p><img src="http://via.placeholder.com/30x15"> <span>regular</span>, the <span class="ovh">overflowed</span> trick</p>
Understanding inline formatting can be challenging. For further insights into its nuances and surprises, check out this article: .
A sensible guideline would be to avoid using display: inline-*
solely for side effects unless you plan on incorporating the element within text. In the scenario described by OP, switching the inner span
to display: block
presents a straightforward solution without intricate line box calculations.