What Is CSS line spacing or CSS line-height?
line-height controls the vertical spacing between lines of text (the “line box” height). It affects readability, layout rhythm, and how inline content sits next to other things.
A helpful mental model: font-size is the height of the letters, while line-height is the height of the invisible “row” the letters live in.
.demo {
line-height: 1;
}
.demo {
line-height: 1.4;
}
.demo {
line-height: 1.8;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 920px;
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.demo {
font-size: 20px;
padding: 14px;
border: 3px solid #111;
background: #f6f6f6;
}
.demo strong {
background: #fff;
padding: 0 6px;
border: 2px solid #111;
}
Line-height can make the same paragraph feel cramped or airy. Try switching snippets and notice how the text breathes as the value increases. This is especially noticeable with longer lines and multi-line text.
line-height vs “leading”
In typography, “leading” is the extra space between baselines. In CSS, you’ll often hear people use “leading” as a synonym for line-height, but technically line-height is the total line box height, not “only the extra.”
Default line-height and why it varies
If you don’t set line-height, browsers use a “normal” value. It’s not a single fixed number; it depends on the font and user agent defaults. That’s why text can look different across fonts even at the same font-size.
.demo {
line-height: normal;
}
.demo {
line-height: 1.5;
}
.demo {
line-height: 2;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.demo {
font-size: 18px;
padding: 14px;
border: 3px solid #111;
background: #f6f6f6;
}
normal is font-dependent. Compare it with a deliberate value like 1.5. Your eyes will usually prefer the deliberate one for paragraphs.
The three main ways to set CSS line-height
You’ll commonly see these value types:
-
Unitless number (recommended most of the time):
line-height: 1.5; -
Length:
line-height: 28px; -
Percentage:
line-height: 150%;
Unitless line-height (the friendly default)
A unitless value is a multiplier of the element’s font-size. So if font-size is 20px and line-height is 1.5, the computed line height becomes 30px.
Why it’s great: when a child element changes its font-size, it keeps a proportional line height. That usually avoids ugly inheritance surprises.
.demo {
font-size: 20px;
line-height: 1.5;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 920px;
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.demo {
padding: 14px;
border: 3px solid #111;
background: #f6f6f6;
}
.demo em {
font-style: normal;
font-weight: 700;
background: #fff;
padding: 0 6px;
border: 2px solid #111;
}
Drag both sliders. Notice how line-height stays proportional as you change the font size. This is why unitless line-height is such a solid default for body text.
Length line-height (px, rem, and friends)
When you use a length, you’re setting an exact line box height. This can be useful for very controlled UI text (like badges, buttons, single-line chips), but it can be risky for paragraphs because it doesn’t scale automatically if the font size changes.
.demo {
font-size: 18px;
line-height: 28px;
}
.demo {
font-size: 24px;
line-height: 28px;
}
.demo {
font-size: 24px;
line-height: 1.4;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.demo {
padding: 14px;
border: 3px solid #111;
background: #f6f6f6;
}
.note {
font-size: 14px;
margin: 0;
opacity: 0.85;
}
Same line-height, different font-size. When the font gets bigger but line-height stays fixed, things get tight fast.Try snippet 2 vs 3.
Percentage line-height
line-height: 150%; is similar to a multiplier, but it behaves like a computed value based on the element’s font size. It’s fine, but most people prefer unitless numbers because they inherit more predictably across nested elements.
.demo {
font-size: 20px;
line-height: 150%;
}
.demo {
font-size: 20px;
line-height: 1.5;
}
.demo {
font-size: 20px;
line-height: 30px;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 920px;
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.demo {
padding: 14px;
border: 3px solid #111;
background: #f6f6f6;
}
Three ways to land on “about” the same spacing. For long-form text, unitless is usually the easiest to maintain.
Inheritance gotchas: unitless vs px
Here’s the surprise: line-height is inherited.
- If the parent uses a unitless line-height, the child inherits the number and recalculates using its own font size (usually good).
- If the parent uses a px line-height, the child inherits that exact px value (often awkward).
.parent {
line-height: 1.6;
}
.parent {
line-height: 26px;
}
.parent {
line-height: 1.6;
}
.child {
line-height: 1.2;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.parent {
padding: 14px;
border: 3px solid #111;
background: #f6f6f6;
font-size: 18px;
}
.child {
display: inline-block;
margin-top: 10px;
padding: 10px 12px;
border: 2px solid #111;
background: #fff;
font-size: 28px;
font-weight: 700;
}
Parent paragraph text sits here and inherits line-height rules. BIG TEXT
Notice how the px-based line-height can make the big child text feel cramped (because it inherits the same fixed line-height). This is why you’ll often see:
body { line-height: 1.5; }h1, h2, h3 { line-height: 1.1; }
Choosing good line-height values
There’s no magic number, but here are practical starting points:
- Paragraphs:
1.4to1.7 - Headings:
1.05to1.25 - Small UI labels:
1.2to1.4
The longer the line length and the smaller the font, the more line-height you typically want.
.p {
font-size: 18px;
line-height: 1.6;
}
.h {
font-size: 42px;
line-height: 1.05;
}
.ui {
font-size: 14px;
line-height: 1.3;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 14px;
font-family: system-ui, Arial, sans-serif;
}
.block {
padding: 14px;
border: 3px solid #111;
background: #f6f6f6;
}
.h {
margin: 0 0 10px 0;
font-weight: 800;
}
.p {
margin: 0;
opacity: 0.95;
}
.ui {
display: inline-block;
padding: 8px 10px;
border: 2px solid #111;
background: #fff;
font-weight: 700;
}
Big heading that wrapsBody text wants breathing room. If your paragraphs feel tiring to read, bump line-height up a bit before you blame your font.
UI label Another label
line-height and inline elements
Inline elements (like span and a) sit inside a line box. That means:
-
A tall
line-heightcan make inline backgrounds look “chunky” (because the line box is taller). - Padding on inline elements can behave unexpectedly (especially vertical padding).
.demo {
line-height: 1.9;
}
.badge {
display: inline-block;
line-height: 1;
}
.badge {
display: inline-flex;
align-items: center;
line-height: 1;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.demo {
font-size: 18px;
padding: 14px;
border: 3px solid #111;
background: #f6f6f6;
margin: 0;
}
.badge {
padding: 6px 10px;
border: 2px solid #111;
background: #fff;
font-weight: 800;
}
Inline stuff: NEW HOT WOW can look weird if the line-height is huge.
A common UI trick: set the surrounding text’s line-height for readability, but give small inline “badge” components their own tighter line-height (and often inline-flex) to keep them visually compact.
line-height and multi-line layout math
When you care about exact heights (like clamping text to 2 or 3 lines), line-height matters because the element’s height is often “number of lines × line-height”.
Even if you don’t use clamping, this mindset helps you reason about why a text block is taller than expected.
The first two CSS Snippets clamp text to 3 lines, where the third snippet clamps text to 2 lines.
.clamp {
line-height: 1.4;
max-height: calc(1.4em * 3);
overflow: hidden;
}
.clamp {
line-height: 1.6;
max-height: calc(1.6em * 3);
overflow: hidden;
}
.clamp {
line-height: 1.4;
max-height: calc(1.4em * 2);
overflow: hidden;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
max-width: 980px;
padding: 18px;
display: grid;
gap: 12px;
font-family: system-ui, Arial, sans-serif;
}
.card {
border: 3px solid #111;
background: #f6f6f6;
padding: 14px;
}
.clamp {
margin: 0;
font-size: 18px;
}
.meta {
margin: 10px 0 0 0;
font-size: 14px;
opacity: 0.85;
}
This paragraph is intentionally long to show “line math”. We’re limiting the height using em-based calculations that track line-height. Try different snippets to see how three lines can become two, or how the spacing changes.
For a more reliable line clamping method, see the CSS Ellipsis Interactive Tutorial.
A practical “text stack” pattern
If you’re building a site (or a design system), a simple approach is:
- Set a comfortable default on
body. - Give headings a tighter line-height.
- Optionally set a utility class for “compact” text.
body {
line-height: 1.6;
}
h2 {
line-height: 1.15;
}
.compact {
line-height: 1.25;
}
body {
line-height: 1.45;
}
h2 {
line-height: 1.1;
}
.compact {
line-height: 1.2;
}
body {
line-height: 1.75;
}
h2 {
line-height: 1.2;
}
.compact {
line-height: 1.35;
}
*,
::before,
::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, Arial, sans-serif;
}
.wrap {
max-width: 980px;
padding: 18px;
}
.panel {
border: 3px solid #111;
background: #f6f6f6;
padding: 14px;
}
h2 {
margin: 0 0 10px 0;
font-size: 34px;
font-weight: 900;
}
p {
margin: 0 0 10px 0;
font-size: 18px;
}
.small {
font-size: 14px;
opacity: 0.9;
margin: 0;
}
Text Stack
Body text should be comfortable. Headings should feel tight and punchy. And sometimes you want a compact block for small UI-ish content.
Compact text can help labels, captions, and metadata feel less “floaty”.
Common mistakes and quick fixes
Mistake: using px line-height everywhere
Fixed line-height can be fine for single-line UI, but it can backfire when text size changes (responsive layouts, user zoom, accessibility settings).
- Fix: use unitless line-height for paragraphs (example:
1.5or1.6).
Mistake: tight line-height on long paragraphs
Tight spacing can look “sleek” in short headings, but it makes paragraphs harder to read.
- Fix: increase line-height, or reduce line length (or both).
Mistake: ignoring inheritance
You set line-height on a container, then wonder why a big child element looks cramped.
- Fix: prefer unitless line-height on parents, and override children when needed.
Mistake: inline badges look too tall
If the surrounding text has a tall line-height, inline backgrounds and padded spans can look vertically oversized.
- Fix: give the badge its own line-height and consider
inline-flex.
CSS Line Height Quick reference
- Best default for paragraphs:
line-height: 1.5;or1.6 - Best default for headings:
line-height: 1.1;to1.2 - Prefer unitless values for scalable, predictable inheritance
- Use lengths for tightly controlled UI (often single-line)
