Intermediate9 min read

CSS Line Height and Vertical Rhythm

9 min read
303 words
14 sections12 code blocks

Line height is one of the most important yet often overlooked properties in CSS typography. Proper line height dramatically improves readability, while vertical rhythm creates visual harmony throughout your entire design. Mastering these concepts separates amateur layouts from professional typography.

Understanding Line Height

The line-height property sets the height of each line box, controlling the space between lines of text. It's the primary tool for improving text readability.

CSS
/* Different ways to set line-height */
p {
  line-height: normal;      /* Browser default (~1.2) */
  line-height: 1.5;         /* Unitless - recommended */
  line-height: 150%;        /* Percentage */
  line-height: 24px;        /* Fixed pixels */
  line-height: 1.5em;       /* Relative to font-size */
}

Why Unitless Values Are Best

Always prefer unitless line-height values. When you use units like em, px, or percentages, the computed value is inherited by child elements. Unitless values, however, allow children to recalculate based on their own font-size.

CSS
/* Problem with em/percentage */
.parent {
  font-size: 16px;
  line-height: 1.5em; /* Computes to 24px, inherited as 24px */
}

.parent .heading {
  font-size: 32px;
  /* Inherits 24px line-height - too tight! */
}

/* Solution: unitless values */
.parent {
  font-size: 16px;
  line-height: 1.5; /* Ratio inherited, not computed value */
}

.parent .heading {
  font-size: 32px;
  /* Computes to 32px × 1.5 = 48px - proportional! */
}

Optimal Line Height for Readability

Research shows that optimal line height depends on line length (measure), font characteristics, and context. Here are practical guidelines:

CSS
/* Body text: 1.5 to 1.7 for comfortable reading */
body {
  font-size: 1rem;
  line-height: 1.6;
}

/* Shorter line lengths can use tighter spacing */
.narrow-column {
  max-width: 45ch;
  line-height: 1.5;
}

/* Wider columns need more spacing */
.wide-column {
  max-width: 75ch;
  line-height: 1.7;
}

/* Headings: tighter line height (1.1 to 1.3) */
h1, h2, h3 {
  line-height: 1.2;
}

/* Small text: slightly more line height */
.small-text {
  font-size: 0.875rem;
  line-height: 1.7;
}

/* Large text: can be tighter */
.large-text {
  font-size: 1.25rem;
  line-height: 1.5;
}

Font-Specific Adjustments

Different fonts have different x-heights and visual densities. A line-height that works for one font may feel too tight or loose for another.

CSS
/* System fonts often need standard line-height */
.system-font {
  font-family: system-ui, sans-serif;
  line-height: 1.5;
}

/* Fonts with large x-height may need more space */
.large-x-height {
  font-family: 'Verdana', sans-serif;
  line-height: 1.6;
}

/* Fonts with small x-height can be tighter */
.small-x-height {
  font-family: 'Georgia', serif;
  line-height: 1.5;
}

Understanding Vertical Rhythm

Vertical rhythm is the concept of maintaining consistent vertical spacing throughout a design, based on a baseline unit. This creates visual harmony and makes layouts feel cohesive.

CSS
:root {
  --baseline: 8px;
  --line-height: 1.5;
  --font-size: 16px;
  /* Line box height: 16px × 1.5 = 24px (3 × baseline) */
}

body {
  font-size: var(--font-size);
  line-height: var(--line-height);
}

/* All spacing uses baseline multiples */
h1 {
  font-size: 2.5rem;
  line-height: 1.2;
  margin-bottom: calc(var(--baseline) * 3); /* 24px */
}

p {
  margin-bottom: calc(var(--baseline) * 3); /* 24px */
}

section {
  padding: calc(var(--baseline) * 6) 0; /* 48px */
}

Building a Vertical Rhythm System

CSS
:root {
  /* Base unit */
  --rhythm-unit: 0.5rem; /* 8px at default font size */

  /* Spacing scale based on rhythm */
  --space-1: var(--rhythm-unit);           /* 8px */
  --space-2: calc(var(--rhythm-unit) * 2); /* 16px */
  --space-3: calc(var(--rhythm-unit) * 3); /* 24px */
  --space-4: calc(var(--rhythm-unit) * 4); /* 32px */
  --space-6: calc(var(--rhythm-unit) * 6); /* 48px */
  --space-8: calc(var(--rhythm-unit) * 8); /* 64px */
}

/* Typography with rhythm */
body {
  font-size: 1rem;
  line-height: 1.5; /* 24px line box = 3 rhythm units */
}

h1 {
  font-size: 2.5rem;
  line-height: 1.2;
  margin-top: var(--space-6);
  margin-bottom: var(--space-3);
}

h2 {
  font-size: 2rem;
  line-height: 1.25;
  margin-top: var(--space-6);
  margin-bottom: var(--space-2);
}

p {
  margin-bottom: var(--space-3);
}

/* Components follow the rhythm */
.card {
  padding: var(--space-3);
  margin-bottom: var(--space-4);
}

.button {
  padding: var(--space-1) var(--space-3);
  line-height: 1.5;
}

Line Height and Multi-line Text

When text wraps to multiple lines, line height becomes even more critical. Consider these patterns:

CSS
/* Multi-line headings */
.hero-title {
  font-size: clamp(2rem, 5vw, 4rem);
  line-height: 1.1; /* Tighter for large display text */
  max-width: 15ch; /* Force wrapping for impact */
}

/* Pull quotes */
blockquote {
  font-size: 1.5rem;
  line-height: 1.4;
  padding-left: 1.5rem;
  border-left: 4px solid currentColor;
}

/* Lists need consistent rhythm */
ul, ol {
  line-height: 1.6;
}

li {
  margin-bottom: 0.5em;
}

Line Height with Inline Elements

Line height affects how inline elements are positioned within line boxes.

CSS
/* Inline elements and line height */
.text-with-icons {
  line-height: 1.5;
}

.text-with-icons svg {
  width: 1em;
  height: 1em;
  vertical-align: middle;
}

/* Inline code */
code {
  font-size: 0.875em;
  padding: 0.125em 0.375em;
  background: #f3f4f6;
  border-radius: 0.25em;
  /* Inherits line-height from parent */
}

Responsive Line Height

Line height may need adjustment at different viewport sizes.

CSS
/* Fluid line height */
body {
  line-height: clamp(1.5, 1.4 + 0.2vw, 1.7);
}

/* Or with custom properties */
:root {
  --body-line-height: 1.6;
}

@media (max-width: 600px) {
  :root {
    --body-line-height: 1.5; /* Tighter on mobile */
  }
}

body {
  line-height: var(--body-line-height);
}

Common Line Height Mistakes

Too Tight

CSS
/* Avoid: difficult to read */
p {
  line-height: 1.2; /* Too tight for body text */
}

Too Loose

CSS
/* Avoid: lines feel disconnected */
p {
  line-height: 2.5; /* Too loose, hard to track to next line */
}

Fixed Values That Don't Scale

CSS
/* Avoid: doesn't scale with font size */
body {
  line-height: 24px;
}

h1 {
  font-size: 3rem;
  /* Still has 24px line-height - broken! */
}

Summary

Line height is fundamental to readable, professional typography. Use unitless values for proper inheritance, adjust based on font size and line length, and build consistent vertical rhythm using a baseline unit. These practices transform your typography from functional to exceptional, creating designs that are both beautiful and comfortable to read.