Why Line-Height Fails to Work as Expected
You've set line-height: 1.5 but the spacing looks wrong. You've inherited values that don't scale. You've got extra space above single-line text that shouldn't be there. If you've ever muttered "line-height is not working," you're not alone--it's one of the most misunderstood properties in CSS.
The secret to solving these problems lies in understanding the line-box model--how browsers actually construct and space text lines. Once you grasp this foundation, every line-height issue becomes diagnosable and fixable.
This guide covers the common reasons line-height appears broken, explains the underlying mechanics, and provides actionable solutions you can apply immediately.
Related resources that complement this guide include our CSS fundamentals guide and our comprehensive typography tutorial.
Understanding the CSS Line-Box Model
To fix line-height issues, you first need to understand what CSS is actually doing under the hood. The line-box model explains why line-height behaves the way it does--and why it often surprises developers expecting print-like behavior.
How Line-Height Actually Works
When the browser renders text with a specific line-height, here's what happens:
- Line Box Creation: For each line of text, the browser creates a rectangular "line box" with a height equal to the element's line-height value
- Vertical Centering: The text content is vertically centered within this line box
- Stacking: Multiple line boxes stack vertically, with adjacent boxes touching at their edges
- Half-Leading Effect: The total line-height value is split equally above and below the text content
This means a single line of text with font-size: 16px and line-height: 32px will have 8px of space above and 8px below the actual text glyphs.
For a deeper dive into how browsers calculate text layouts, see our guide on CSS rendering fundamentals.
1/* Single line with equal font-size and line-height */2.element {3 font-size: 32px;4 line-height: 32px;5 background-color: #e3e8f4;6}7 8/* Result: 32px tall line box with text centered9 Space appears above AND below the text content */Line-Height vs. Traditional Leading
Understanding the historical context helps explain why CSS line-height often surprises developers:
| Aspect | Print Leading | CSS Line-Height |
|---|---|---|
| Space addition | Between lines only | Above AND below each line |
| Control | Physical lead strips | Computed line box height |
| Inheritance | N/A | Inherited with variations |
| Consistency | Varies by typesetter | Browser-calculated |
The term "leading" (pronounced "led-ing") comes from the physical strips of lead that typesetters inserted between lines of metal type. CSS line-height is conceptually related but mechanically different--it's more like adding padding to both sides of each text line.
As explained in CSS-Tricks' comprehensive guide to line height, this difference in mechanics leads to common confusion when developers expect print-like behavior from web typography.
Common Reasons Line-Height Appears Not to Work
Inheritance Issues: Unitless vs. Resolved Values
The most common source of "line-height not working" confusion is how different value types behave during inheritance. This distinction trips up developers every day.
Unitless values multiply against font-size:
.parent {
line-height: 1.5;
}
.child {
font-size: 24px;
/* Computed line-height: 24px × 1.5 = 36px */
}
Unit-based values resolve to pixels and inherit fixed:
.parent {
font-size: 16px;
line-height: 150%;
/* Computed line-height: 16px × 1.5 = 24px */
}
.child {
font-size: 24px;
/* Still inherits 24px (not 36px!) */
}
This means nested headings often appear to have "wrong" line-height when parent elements use percentage or em-based values.
According to the MDN Web Docs on CSS line-height, this inheritance behavior is specified and consistent across browsers, but often surprises developers who expect percentage-based values to scale with each element's font-size.
Margin and Padding Interference
Often what appears to be a line-height problem is actually margin or padding behavior. Developers frequently confuse:
- Space between elements: Caused by margin, not line-height
- Space within an element's background: May be line-height or padding
- First/last line spacing: Often line-height, but check element padding first
A useful debugging technique: set outline: 1px solid red on the element to visualize its actual box boundaries versus where the text sits within.
For more debugging techniques, see our guide on CSS box model debugging.
Understanding the box model is essential because line-height operates differently than padding and margin in determining element dimensions and spacing.
Inline Elements and Edge Cases
Line-height behaves differently depending on the element type:
- Block elements: line-height affects the line boxes within and can increase the element's total height
- Inline elements (span, a): line-height affects line box height but not the element's own height
- Replaced elements (img, video): completely ignore line-height for their positioning
This is why applying line-height to an inline element with a background color might not produce the visual effect you expect--the background only covers the content area, not the full line box.
If you're working on CSS login page techniques, understanding how line-height interacts with inline and block elements is crucial for proper form styling.
Font-Family Variations
Different fonts have different baseline positions, x-heights, and descender depths. The same line-height value can produce visually distinct results across fonts. A font with a tall x-height will appear to have tighter line spacing than one with a small x-height, even with identical line-height values.
As noted in the CSS-Tricks typography guide, understanding these font-specific characteristics is essential for consistent typography across different typefaces.
Line-Height Values Explained
The normal Keyword
The normal keyword relies on browser defaults, typically 1.0 to 1.2 depending on the font-family. It's user-agent dependent, meaning different browsers may render it slightly differently.
body {
line-height: normal; /* Browser default, varies by font */
}
While normal works for default body text, it lacks consistency for design systems where predictable spacing matters.
Unitless Numbers: The Recommended Approach
Unitless values are the gold standard for most use cases:
/* Recommended for body text */
p {
line-height: 1.5;
}
/* Tight heading spacing */
h1, h2, h3 {
line-height: 1.2;
}
/* Extra readability for dense content */
.article-body {
line-height: 1.6;
}
Why unitless wins:
- Scales proportionally with font-size changes
- Inherits correctly across nested elements
- Supports user font size preferences
- Accessible by default
The DigitalOcean line-height tutorial emphasizes that unitless values are the preferred approach for maintaining responsive and accessible typography.
| Value Type | Inheritance | Responsive | Best For |
|---|---|---|---|
| normal | Varies by browser | No | Default body text |
| 1.5 (unitless) | Scales with font-size | Yes | Most text content |
| 150% | Fixed computed value | No | Avoid when possible |
| 1.5em | Fixed computed value | No | Legacy code only |
| 24px | Fixed pixel value | No | Heading-specific only |
Length Values: When to Use Each
Pixels (px):
- Absolute and predictable
- Doesn't scale with user preferences
- Best for: Specific design elements that need exact spacing
rem units:
- Relative to root font-size
- More predictable than em for inheritance
- Good for: Design systems with consistent rhythm
em units:
- Relative to element's font-size
- Creates fixed inheritance (problematic)
- Avoid for: line-height (prefer unitless or rem)
Percentage Values
Percentages calculate against the element's own font-size, then resolve to a pixel value that inherits as fixed:
.parent {
font-size: 16px;
line-height: 150%; /* Resolves to 24px */
}
.child {
font-size: 32px;
/* Still inherits 24px, not 48px! */
}
This is almost never the desired behavior for responsive typography.
For consistent centering techniques, use unitless line-height values combined with flexbox or grid layouts.
Line-Height Performance Impact
1.5
Minimum for accessible body text
<4ms
Average render time impact
0
Layout recalculations triggered
Performance Considerations
Line-height is one of the more performant CSS properties, but understanding its impact helps in optimization scenarios.
When Line-Height Affects Layout
Most of the time, line-height only affects inline formatting and doesn't trigger layout recalculation. However, line-height can impact layout when:
- The element has a visible background or border
- The element participates in flexbox or grid layouts
- The computed line-height exceeds the element's content area
Animation and Transitions
Avoid animating line-height as it can trigger layout recalculation on each frame. For animated text effects:
- Use CSS transforms instead
- Consider opacity or scale animations
- Use line-height only for static states
Font Loading Impact
When fonts load, line-height calculations may need recalculation. This is why using system fonts initially and progressively enhancing can prevent layout shifts related to line-height changes.
Practical Performance Tips
- Use unitless values to avoid inheritance recalculations
- Set line-height on the root element for consistent baseline
- Avoid changing line-height in media queries--font-size changes handle most responsive needs
For more on CSS performance, see our guide on CSS optimization techniques.
Accessibility Requirements and Best Practices
Minimum Line-Height for Readability
According to MDN Web Docs accessibility guidelines and WCAG guidelines:
- Body paragraphs: Minimum 1.5 (1.5 to 1.7 is ideal)
- Headings: Can be tighter (1.1 to 1.3)
- Navigation text: 1.3 to 1.5 for readability
- Legal/disclaimer text: 1.5 minimum due to critical content
Implementing Accessible Typography
/* Base typography with accessibility in mind */
body {
font-size: 16px; /* Minimum recommended */
line-height: 1.5; /* WCAG minimum */
}
p {
margin-bottom: 1em; /* Space between paragraphs */
line-height: 1.5; /* Consistent with body */
}
/* Headings can be tighter but still readable */
h1, h2, h3 {
line-height: 1.2;
}
Supporting User Adjustments
WCAG 2.2 requires that text spacing can be adjusted by users without losing content or functionality. Avoid:
- Fixed pixel values that don't scale
- Hardcoded line-heights that prevent user override
- Container constraints that truncate adjusted text
For comprehensive accessibility guidance, see our web accessibility best practices.
When implementing CSS background images on text containers, ensure line-height adjustments maintain readability across different visual treatments.
Key recommendations for consistent, accessible line-height
Use Unitless Values
Prefer 1.5 over 150% or 1.5em for predictable inheritance and responsive scaling
Test with Different Fonts
Line-height visually varies by font--test your design with actual fonts used
Meet Accessibility Minimums
Maintain 1.5 minimum for body text per WCAG guidelines
Debug with Outlines
Use CSS outlines to visualize line boxes versus element boxes
Common Fixes for "Not Working" Scenarios
Scenario 1: Too Much Space Around Single Line
Problem: line-height: 1.5 adds unwanted space above text
Solution: Check if a parent element has a larger inherited line-height. Use unitless values consistently:
/* Fix: Ensure consistent unitless inheritance */
.parent {
line-height: 1.2; /* Match heading needs */
}
.child {
line-height: 1.5; /* Independent body text spacing */
}
Scenario 2: Text Overlapping on Next Line
Problem: Lines are too close together, causing overlap
Solution: Increase line-height or reduce font-size:
/* Increase spacing */
p {
line-height: 1.6;
}
Scenario 3: Nested Element Has Wrong Line-Height
Problem: Child element doesn't inherit expected value
Solution: Identify if parent uses unit-based values. Switch to unitless:
/* Before: Fixed inheritance */
.parent {
line-height: 150%; /* Computes to fixed pixels */
}
/* After: Scalable inheritance */
.parent {
line-height: 1.5; /* Multiplies with font-size */
}
Scenario 4: Different Behavior Across Browsers
Problem: Chrome, Firefox, Safari render differently
Solution: Check font loading and fallback fonts:
/* Specify fallback fonts for consistency */
body {
font-family: 'Your Font', system-ui, sans-serif;
line-height: 1.5;
}
For more CSS troubleshooting, see our guide on common CSS problems and solutions.
Related techniques include our tutorials on CSS triangles and CSS div height which demonstrate practical applications of CSS box model concepts.
Frequently Asked Questions
Sources
-
MDN Web Docs: line-height - Official documentation for CSS line-height property, values, and accessibility requirements
-
CSS-Tricks: How to Tame Line Height in CSS - Advanced typography techniques and line-box model explanation
-
DigitalOcean: CSS line-height Tutorial - Practical examples and readability guidelines