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:

  1. Take the font's ascender and descender to get the natural content height;
  2. Subtract that from line-height and split the remainder evenly above and below (half-leading);
  3. 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