The four kinds of line-height
Last updated 2026-11-02
On this page
line-height decides how tall one line of text is. Three of its four values look interchangeable, but they inherit in completely different ways — the most commonly stepped-on trap in CSS.
The four values
| Value | Example | Meaning |
|---|---|---|
normal |
line-height: normal |
Whatever the browser derives from font metrics, usually around 1.2× the font size |
| number | line-height: 1.5 |
A multiple of the font size, computed against the current font-size |
| length | line-height: 24px |
A fixed height, independent of font size |
| percentage | line-height: 150% |
A percentage of the current font-size, computed to a fixed value |
Inheritance is where it bites
Take a parent:
.parent {
font-size: 16px;
line-height: 1.5; /* or 24px, or 150% */
}
.child {
font-size: 32px;
}
| Parent wrote | Child inherits | Child's line height |
|---|---|---|
1.5 (number) |
the number 1.5 itself |
32 × 1.5 = 48px |
24px (length) |
24px | 24px — smaller than the text, lines collide |
150% (percentage) |
the already-computed 24px | 24px — same collision |
Only a unitless number is passed down as a ratio. Lengths and percentages are resolved at the parent and inherited as absolute values.
So "the parent says line-height: 1.5 but the headline looks wrong" has two causes: the parent actually wrote 150% or 1.5em, or the headline sets a fixed value of its own.
How a line box is built
The height of a line is not the height of the letters; it is a line box:
- Take the font's ascender and descender to get the natural content height;
- Subtract that from
line-heightand split the remainder evenly above and below (half-leading); - Align inline boxes on the baseline by
vertical-align, then take the tallest.
That is why increasing line-height pushes text apart both up and down, and why two fonts at the same line-height can still look differently spaced — their natural heights differ.
What normal actually is
normal is not "1.2"; it is "whatever the browser derives from the font metrics". The spec suggests an algorithm using ascender, descender and line gap, so the number varies by browser and by font.
Never treat normal as a constant: the same CSS can produce different leading in Chrome, Safari and Firefox, and changing the font changes it too.
In practice
:root {
--leading-tight: 1.25;
--leading-normal: 1.6;
}
body {
font-size: 1rem;
line-height: var(--leading-normal);
}
h1,
h2,
h3 {
line-height: var(--leading-tight);
}
- Use a unitless number on the root so the whole site scales together;
- Give large headings a tighter multiple (bigger text needs proportionally less leading);
- Use lengths only when you must hit a grid (say every line is exactly 24px) — and then compute it at every level that changes font size.
Related to the font itself
hhea.ascender / descender / lineGap (and the two sets in OS/2) decide what "one line" naturally is. See head / hhea / post.
Further reading
- MDN:
line-height - CSS Inline Layout: line boxes and half-leading