htmlcsstypographyline-height

Some line-height values on inline elements results in strange container heights


Consider the following code (an inline <span> contained within a block-level <div>):

<div>
    <span style="font-size:40px;line-height:3px;">HELLO</span>
</div>

This will result in the <div> having a height of 19px. How did the browser arrive at this value of 19px?

The following snippet is that code in action:

<!doctype html>
<html lang="en" style="font-family:'Arial';">
<head>
    <meta charset="utf-8"/>
    <title>Line-Height Test</title>
</head>
<body style="padding-top:50px;padding-right:calc(100% - 300px);">
<div id="greenDiv" style="background-color:lightgreen;">
    <span style="font-size:40px;line-height:3px;">HELLO</span>
</div>
<div id="infoDiv" style="margin-top:20px;"></div>
<script>
    (() => {
        const infoDiv = document.getElementById("infoDiv");
        const greenDiv = document.getElementById("greenDiv");
        let html = `The inner &lt;span&gt; is ${greenDiv.firstElementChild.offsetHeight}px tall,`;
        html += ` but its container (the outer green &lt;div&gt;) is only ${greenDiv.offsetHeight}px tall.`;
        html += `<br/>How did the browser arrive at this ${greenDiv.offsetHeight}px value?`;
        infoDiv.innerHTML = html;
    })();
</script>
</body>
</html>


Solution

  • To better understand, make the line-height equal to 0 and you will get a height equal to 18px for the div. The div has the default font-size equal to 16px and the default line-height is equal to normal. The normal value is based on the font and in this case it seems to be equal to 1.125 to have 18px = 1.125 * 16px

    <!doctype html>
    <html lang="en" style="font-family:'Arial';">
    <head>
        <meta charset="utf-8"/>
        <title>Line-Height Test</title>
    </head>
    <body style="padding-top:50px;padding-right:calc(100% - 300px);">
    <div id="greenDiv" style="background-color:lightgreen;">
        <span style="font-size:40px;line-height:0;">HELLO</span>
    </div>
    <div id="infoDiv" style="margin-top:20px;"></div>
    <script>
        (() => {
            const infoDiv = document.getElementById("infoDiv");
            const greenDiv = document.getElementById("greenDiv");
            let html = `The inner &lt;span&gt; is ${greenDiv.firstElementChild.offsetHeight}px tall,`;
            html += ` but its container (the outer green &lt;div&gt;) is only ${greenDiv.offsetHeight}px tall.`;
            html += `<br/>How did the browser arrive at this ${greenDiv.offsetHeight}px value?`;
            infoDiv.innerHTML = html;
        })();
    </script>
    </body>
    </html>

    Now, if you start increasing the line-height of the span, the height of the div will increase due to the vertical alignment. This is a bit tricky because we need some complex calculation to identify the final height but if you change the alignment of the span to something different from baseline (the default one), the height will get back to 18px whataver the line-height

    <!doctype html>
    <html lang="en" style="font-family:'Arial';">
    <head>
        <meta charset="utf-8"/>
        <title>Line-Height Test</title>
    </head>
    <body style="padding-top:50px;padding-right:calc(100% - 300px);">
    <div id="greenDiv" style="background-color:lightgreen;">
        <span style="font-size:40px;line-height:18px;vertical-align: top">HELLO</span>
    </div>
    <div id="infoDiv" style="margin-top:20px;"></div>
    <script>
        (() => {
            const infoDiv = document.getElementById("infoDiv");
            const greenDiv = document.getElementById("greenDiv");
            let html = `The inner &lt;span&gt; is ${greenDiv.firstElementChild.offsetHeight}px tall,`;
            html += ` but its container (the outer green &lt;div&gt;) is only ${greenDiv.offsetHeight}px tall.`;
            html += `<br/>How did the browser arrive at this ${greenDiv.offsetHeight}px value?`;
            infoDiv.innerHTML = html;
        })();
    </script>
    </body>
    </html>

    I am using line-height: 18px with a top alignment and the total height is still 18px. If I increase the line-height of the span, the height will also increase. If you update the alignment the height will also increase.

    To conclude, the line-height and font-size of the div will set a minimum height. This minimum height can be changed by the line-height of the inner element and their vertical alignment.

    Related questions:

    How does height will be calculated, based on font-size?

    Why inline and inline-block have different height with the same text content

    How to determine height of content-box of a block and inline element