Line Height Best Practices
The Problem
Line height is one of the most misunderstood CSS properties. AI agents frequently use values with units (line-height: 24px or line-height: 1.5em), which causes inheritance problems when child elements have different font sizes. The result is text that is either too cramped or too spaced, especially in components where font sizes vary between headings, body text, and small text.
The Solution
Use unitless line-height values. A unitless value is inherited as a ratio, meaning each element recalculates its actual line height based on its own font size. This prevents the common bug where a parent's computed line-height in pixels is inherited by children with different font sizes.
How Unitless vs Unit-Based Inheritance Works
/* PROBLEMATIC: unit-based line-height */
.parent {
font-size: 16px;
line-height: 24px; /* computed: 24px */
}
.parent h2 {
font-size: 32px;
/* Inherits line-height: 24px — text overlaps! */
}
/* CORRECT: unitless line-height */
.parent {
font-size: 16px;
line-height: 1.5; /* computed: 24px (16 × 1.5) */
}
.parent h2 {
font-size: 32px;
/* Inherits line-height ratio 1.5 → computed: 48px (32 × 1.5) */
}
Code Examples
Recommended Values by Element Type
:root {
/* Base line-height for body text */
line-height: 1.5;
}
/* Body text: 1.5 to 1.6 for optimal readability */
p,
li,
dd,
blockquote {
line-height: 1.5;
}
/* Headings: tighter line-height since large text needs less leading */
h1 {
line-height: 1.1;
}
h2 {
line-height: 1.2;
}
h3 {
line-height: 1.3;
}
h4,
h5,
h6 {
line-height: 1.4;
}
/* Small text / captions: slightly more line-height for readability */
small,
.caption,
.footnote {
line-height: 1.6;
}
/* Code blocks: tighter to keep code compact */
pre,
code {
line-height: 1.4;
}
Line Height with Fluid Typography
:root {
--line-height-tight: 1.1;
--line-height-snug: 1.3;
--line-height-normal: 1.5;
--line-height-relaxed: 1.6;
--line-height-loose: 1.8;
}
h1 {
font-size: clamp(2rem, 1.5rem + 2.5vw, 3.5rem);
line-height: var(--line-height-tight);
}
p {
font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
line-height: var(--line-height-normal);
}
Using the lh Unit for Spacing
The lh unit represents the computed line-height of the element, enabling spacing that aligns with the text rhythm.
p {
line-height: 1.5;
margin-block-end: 1lh; /* Margin equals one line of text */
}
blockquote {
line-height: 1.5;
padding-block: 0.5lh; /* Half a line of padding */
border-inline-start: 0.125lh solid currentColor;
}
Common AI Mistakes
- Using
line-height: 24pxorline-height: 1.5eminstead of the unitless1.5, causing inheritance bugs - Applying the same
line-heightto headings and body text — headings need tighter values (1.1 to 1.3) - Setting
line-height: 1(or thenormalkeyword) for body text, which is too tight for readability. Thenormalkeyword typically resolves to around 1.2 depending on the font, which is below the WCAG recommendation - Using
line-height: 2or higher for body text, which creates excessive spacing and makes paragraphs look disconnected - Forgetting that
line-heightaffects the clickable area of inline elements and links - Not accounting for the font's built-in metrics — some fonts (especially decorative ones) need different line-height values than standard sans-serif fonts
When to Use
Every text element should have an intentional line-height value. The general guidelines are:
- Body text (paragraphs, lists): 1.5 to 1.6 — this meets WCAG 1.4.12 (Text Spacing) requirements
- Headings: 1.1 to 1.3 — large text reads well with tighter leading
- Display / hero text: 1.0 to 1.15 — very large text can be even tighter
- Small text / captions: 1.5 to 1.7 — small text benefits from extra breathing room
- UI elements (buttons, badges): 1 to 1.2 — where vertical centering matters more than reading flow