Explanation:
There are a few things happening here.
In your example, the small
element is an inline-level element, which means that its vertical alignment is determined by the vertical-align
property.
The default vertical-align
value is baseline
, which means that the baseline of the small
element will be aligned to the baseline of the parent box:
Align the baseline of the box with the baseline of the parent box. If the box does not have a baseline, align the bottom margin edge with the parent's baseline.
Next, you need to consider the line-height
property and how it is calculated. You also need to take leading and half-leading into account. In CSS, half-leading is determined by finding the difference between the element's line-height
and font-size
, dividing that in half, and then placing the calculated amount of space above and below the text.
For illustration, here is an example image demonstrating this (taken from W3.org):
Since the line-height
is 20px
, and the small
element has a font-size
of 13px
, then we can determine that 3.5px
of space is added above and below the small
element's text:
(20px - 13px) / 2 = 3.5px
Likewise, if we calculate the half-leading of the surronding text nodes, which have a font-size
of 16px
, then we can determine that 2px
of space is added above and below the surrounding text.
(20px - 16px) / 2 = 2px
Now if we relate these half-leading space calculations back to the vertical-align
property, you will notice that more space is actually being added below the baseline of the small
element. This explains why the computed height of the p
element containing the small
element was larger than the computed height of the other p
element.
With that being said, you would expect the computed height of the p
element to continue increasing as the font-size
of the small
element decreases. To further illustrate this point, you will notice that the computed height of the p
element is 23px
when the font-size
of the small
element is set to 6px
.
p { line-height: 20px; }
small { font-size: 6px; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>
Potential Workarounds:
Since we know that the height difference results from the extra space that is added to the baseline
, we could change the vertical-align
value of the small
element to top
:
p { line-height: 20px; }
small { vertical-align: top; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>
Alternatively, you could give the small
element a line-height
of 17px
, which would result in 2px
of space being added above and below the element (which is the same amount of space that is added for the surrounding text like we calculated above).
// Surrounding text that is 16px:
(20px - 16px) / 2 = 2px
// Small element text that is 13px:
(17px - 13px) / 2 = 2px
p { line-height: 20px; }
small { line-height: 17px; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>
However, you really don't want to be calculating any of that and hardcoding it, which means that you should just use a relative line-height
and omit the px
units.
Since the the font-size
is 16px
and the desired line-height
value is 20px
, you would divide the line-height
by the font-size
and get 1.25
:
p { line-height: 1.25; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>
If you don't want to use a relative line-height: 1.25
, and you want to continue using line-height: 20px
, then you could of course reset the small
element's line-height
value back to the initial value, which is normal
.
p { line-height: 20px; }
small { line-height: normal; }
<p>some normal-sized text</p>
<p>some <small>small</small>-sized text</p>
small
element by aspan
element and test with different font sizes, you’ll notice that anything smaller (even by one pixel) than the parent element’s font size makes the parent element 21px tall, whereas a larger font size up to 19px does not do that (the height stays at 20px). – Handle