DESIGN DETAILS · 8 MIN READ

Line height and letter spacing: the invisible difference

How to set line height and letter spacing in CSS: unitless values, ranges for body and headings, line length, WCAG text spacing and how to inspect it.

Set line-height as a unitless number: roughly 1.4 to 1.7 for body text and 1.0 to 1.25 for large headings. Set letter-spacing in em so it scales with the text, add a little to uppercase labels, tighten large display sizes slightly, and leave body text alone. Keep lines to about 45 to 75 characters, because line length and line height work together.

Space is part of the type

Typography is more than the shape of a letter. The gaps between characters and between lines set the pace of reading. Two sites can use the same typeface at the same size, and one feels calm while the other feels cramped. The difference is almost always spacing.

So before replacing a typeface that feels crowded, inspect its size, line height, letter spacing and container width. Change one property at a time so you can tell which adjustment helped.

Print termCSS propertyWhat it controls
Leadingline-heightThe vertical distance from one line of text to the next
Trackingletter-spacingUniform extra space added between all characters
Kerningfont-kerningAdjustments for specific letter pairs, such as A and V, stored in the font
Measuremax-widthThe length of a line of text
Line height vs leading They describe the same idea from different eras. Leading was the strip of lead placed between lines of metal type, so it meant only the added space. CSS line-height is the full height of the line. The browser splits the extra space and places half above and half below the text.

Unitless, px or percent: why the unit matters

Line height controls the height of each line box. A unitless value multiplies the element’s own font size: 16px text at 1.5 produces a 24px line height. You can also write 24px, 1.5em or 150%, and on a single element the result is identical. The difference appears in the children, because of how each form is inherited.

/* Percentage or em: the computed length is inherited */
article {
  font-size: 16px;
  line-height: 150%; /* computes to 24px */
}

article h2 {
  font-size: 40px; /* inherits 24px, so two-line headings overlap */
}
The heading is taller than its own line box.
/* Unitless: the number is inherited and recalculated per element */
article {
  font-size: 16px;
  line-height: 1.5; /* 24px here */
}

article h2 {
  font-size: 40px;   /* would inherit 1.5, which is 60px */
  line-height: 1.15; /* 46px: tighter on purpose */
}
Each element computes its line height from its own font size.
ValueWhat is inheritedVerdict
1.5The number. Every child multiplies it by its own font sizeUse this almost always
150% or 1.5emThe computed length, such as 24pxAvoid. Breaks when children change size
24pxThe fixed lengthOnly for single-line UI such as buttons, where you want an exact height
normalThe keyword. Each font supplies its own default, often around 1.2Unpredictable between fonts. Set a number instead

A unitless value also behaves well when someone zooms the page or raises the default text size, because the line height scales with the text.

How much line height? Ranges that work

There is no single best line height. Treat these ranges as starting points, then adjust by eye with your real font and content.

Text roleTypical line heightNotes
Body paragraphs1.4 to 1.71.5 is a safe default and matches accessibility guidance for main content
Large headings and display text1.0 to 1.25Big type carries plenty of space inside the letters already
Subheadings1.2 to 1.35Between the two, moving closer to body text as size drops
Captions and small print1.4 to 1.6Small text needs room as much as body text does
Buttons and labels1 to 1.3Usually one line, so padding does the spacing work

The pattern: the larger the text, the smaller the ratio. Three more things push the number up or down.

  • x-height. Fonts with tall lowercase letters look denser and want more line height. Fonts with small lowercase letters and long ascenders can take less.
  • Line length. Long lines need more space between them so the eye can find the start of the next line.
  • Weight and color. Heavy text, and light text on a dark background, feel tighter and benefit from a little extra.

A large heading often needs a much tighter value than a paragraph. Test it across two or three lines, especially with accents and descenders, and never clip it with a fixed-height container. If your sizes come from a system, store a line height with every step. We show how in build a typography scale.

Line length changes everything

The measure is the number of characters in a line. A long-standing guideline for comfortable reading is about 45 to 75 characters per line, spaces included. WCAG’s strictest level asks for no more than 80. Shorter than the range and the eye jumps too often. Longer and it loses its place on the way back.

.prose {
  max-width: 65ch;
  line-height: 1.6;
}

.sidebar-note {
  max-width: 40ch;
  line-height: 1.45;
}
The ch unit is the width of the 0 glyph in the current font, so the limit follows the typeface and size.

Measure and line height move together. A narrow column reads well at 1.4. A wide article column may need 1.6 or 1.7. If you cannot change the width of a container, change its line height.

Letter spacing: adjust tracking with a light touch

letter-spacing adds the same amount of space after every character, and negative values remove it. Set it in em. A value of 0.08em stays proportional at any size. A value of 1px is large on 12px text and invisible on a 64px headline.

SituationTypical valueWhy
Body textnormalThe type designer already spaced the font for reading. Tracking paragraphs makes them tiring
Uppercase labels and small caps0.05em to 0.1emCapitals are spaced to sit next to lowercase letters. On their own they look cramped
Large display headings-0.01em to -0.03emDefault spacing looks loose at big sizes. A slight tightening pulls the words together
Very small text0 to 0.02emA touch of extra space can help letters stay distinct
.eyebrow {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.hero-title {
  font-size: 4rem;
  line-height: 1.05;
  letter-spacing: -0.02em;
}
  • Negative tracking that suits a 64px heading becomes hard to read at small sizes. If the heading shrinks on phones, relax the tracking there too.
  • Do not letter-space scripts whose letters join, such as Arabic. It breaks the connections between letters.
  • Tracking is not kerning. Kerning is the pair-by-pair adjustment stored in the font, controlled by font-kerning. The default auto lets the browser decide, and normal asks for it to be applied. There is rarely a reason to set none.
  • Large values in either direction make words unreadable. Stay subtle.

WCAG 1.4.12: let readers change the spacing

Some people read with their own spacing, applied through a browser extension, a bookmarklet or a user stylesheet. WCAG success criterion 1.4.12 Text Spacing, at level AA, says your page must not lose content or functionality when a reader sets all of the following:

  • Line height to at least 1.5 times the font size.
  • Spacing following paragraphs to at least 2 times the font size.
  • Letter spacing to at least 0.12 times the font size.
  • Word spacing to at least 0.16 times the font size.

Read that carefully. The criterion does not require you to design with these values. It requires your layout to survive them. To test, apply them to your own page and look for clipped or overlapping text.

/* Temporary test styles for WCAG 1.4.12 */
* {
  line-height: 1.5 !important;
  letter-spacing: 0.12em !important;
  word-spacing: 0.16em !important;
}

p {
  margin-bottom: 2em !important;
}

What usually breaks: a fixed height on cards, buttons and navigation bars, overflow: hidden on text containers, and white-space: nowrap on long labels. Use min-height and padding so boxes can grow with their text. Spacing is one half of readable text. The other half is color, covered in how to check text contrast.

Two newer helpers: text-wrap balance and pretty

Spacing problems often show up as bad line breaks: a heading with a single word on its last line, or a paragraph that ends in an orphan. Two values of text-wrap help.

h1,
h2,
h3 {
  text-wrap: balance;
}

p {
  text-wrap: pretty;
}
  • balance evens out the length of the lines. It works in current versions of Chrome, Edge, Firefox and Safari. Browsers only apply it to short blocks, six lines or fewer in Chromium and ten or fewer in Firefox, so it is meant for headings and captions.
  • pretty asks the browser to use a slower algorithm that favors better layout, for example by avoiding a lone last word. Support is narrower than for balance.
  • Both are safe to ship. A browser that does not understand the value wraps the text as usual.

How to inspect spacing on a live site

Reading the values other sites use is the quickest way to train your eye. Here is the manual route in Chrome or Edge.

  1. Right-click the text and choose Inspect, then open the Computed tab.
  2. Find font-size and line-height. The computed line height is shown in pixels, so divide it by the font size to get the ratio. 28.8px over 18px is 1.6.
  3. If line-height says normal, the site never set it and the font’s own default applies.
  4. Find letter-spacing. It is also reported in pixels. Divide by the font size to get the em value: -0.64px over 32px is -0.02em.
  5. Check the width of the text container to estimate the measure.

The longer walkthrough, including Firefox and Safari, is in how to find font size and line height.

Read the line height ratio without the arithmetic.

Font Inspector shows line height in px and as a ratio, next to the font size and letter spacing of any text you click. Click a value to copy it.

Add to Chrome

With Font Inspector, click the text and the panel shows the size in px, em and rem, the line height in px and as a ratio, and the letter spacing, together with the family and weight that explain why those numbers were chosen. When you want to reuse the whole style, copy it as CSS, Tailwind classes or SCSS variables. If you need to convert a pixel value you found, the px to rem converter does it for any base size.

Questions & answers

What is the best line height for body text?+

A unitless value between about 1.4 and 1.7 suits most body text, and 1.5 is a safe default that matches accessibility guidance. Use more for long lines and fonts with a tall x-height, and less for narrow columns.

Should line-height have a unit in CSS?+

Usually not. A unitless number is inherited as a multiplier, so every child element computes line height from its own font size. Values in px, em or percent are inherited as a fixed length and can make large headings overlap.

What is the difference between line height and leading?+

Leading is the print term for the space added between lines. CSS line-height sets the full height of each line, and the browser places the extra space half above and half below the text.

How do I set tracking in CSS?+

Use letter-spacing with an em value so it scales with the font size, for example letter-spacing: 0.08em on uppercase labels or -0.02em on a large headline. Leave body text at normal.

What does WCAG require for text spacing?+

Success criterion 1.4.12 requires that no content or functionality is lost when a user sets line height to 1.5, paragraph spacing to 2 times the font size, letter spacing to 0.12em and word spacing to 0.16em. It tests your layout’s flexibility, not your default values.

Related free tools: PX to REM converter · Type scale calculator

Sources and further reading: MDN: line-height · MDN: letter-spacing · MDN: font-kerning · MDN: text-wrap · W3C: Understanding Success Criterion 1.4.12 Text Spacing · W3C: Understanding Success Criterion 1.4.8 Visual Presentation

How to find the font size, weight and line height of any text

Read the exact font size, weight, line height and letter spacing of any text on a website, and convert the pixel values into rem, em and a ratio.

Build a typography scale that feels like a system

Build a type scale: pick a base size and a ratio, compute the steps in rem, make headings fluid with clamp(), and ship it as CSS or Tailwind tokens.

Copy any website’s typography as CSS, Tailwind or SCSS

Read a text style from any website with DevTools, clean it up, and rewrite it as portable CSS, Tailwind classes or SCSS variables. Or copy it in one click.