Responsive Typography with CSS

Make text readable on every screen: rem units, fluid font sizes with clamp(), a type scale, line length with ch, line height, and text that respects user settings.

Lesson 37 of 49Intermediate16 min read

Text is most of what people come to a web page for, so it has to be easy to read everywhere. A 64-pixel heading that looks bold and confident on a laptop can take up half the screen on a phone, and lines of body text that stretch across a wide monitor are tiring to follow. Responsive typography adjusts sizes, spacing and line lengths so reading feels comfortable at every width.

There are two parts to getting it right. The first is choosing the right units: rem for font sizes so text respects the reader's browser settings, unitless line-height, and ch for line length. The second is scaling: using clamp() to make headings and spacing grow smoothly between a minimum and a maximum, instead of jumping at breakpoints.

In this lesson you'll set up a solid base, build a fluid type scale, keep paragraphs to a readable width, and use newer properties such as text-wrap: balance for tidy headings. You already know the font properties from CSS fonts and the maths from calc() and clamp(); here you'll put them to work.

Use rem for font sizes

Browsers have a default font size, usually 16px, and readers can change it in their settings. rem units are relative to that root size:

ValueWith the default 16pxIf the reader sets 20px
1rem16px20px
1.25rem20px25px
2rem32px40px

If you write font-size: 16px, you override the reader's choice. Using rem keeps text accessible. Avoid setting html { font-size: 62.5%; } just to make maths easier; it shrinks every unstyled element and makes third-party widgets tiny.

Fluid sizes with clamp()

CSS
h1 { font-size: clamp(2rem, 1.2rem + 3.5vw, 3.5rem); }
h2 { font-size: clamp(1.5rem, 1.1rem + 2vw, 2.25rem); }
p  { font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem); }
  • The first value is the minimum (phones), the last is the maximum (wide screens).
  • The middle value mixes rem and vw, so the size grows with the screen but still responds to zoom and the reader's font setting.
  • Headings change most; body text changes only a little.

A type scale is a set of sizes that relate to each other, such as each heading being 1.25 times the size below. Store your scale in variables like --step-0 to --step-4, and use them everywhere.

Line length and line height

PropertyRecommendationWhy
max-width on text60ch to 75chLong lines make it hard to find the next line
line-height1.5 to 1.7 for body, 1.1 to 1.25 for headingsBig headings need less space between lines
margin between paragraphsabout 1em to 1.5emClear separation without big gaps
letter-spacingSlightly negative on large headings, slightly positive on small capsFine-tunes the look

ch is the width of the "0" character in the current font, so max-width: 65ch keeps lines to about 65 characters whatever the font size. Use unitless line heights such as 1.6, so the spacing scales with each element's font size.

Tidier wrapping

  • text-wrap: balance spreads a heading's words evenly across its lines, avoiding one long line followed by a single word.
  • text-wrap: pretty avoids leaving a single short word alone on the last line of a paragraph.
  • hyphens: auto with a lang attribute on the page breaks long words in narrow columns.
  • overflow-wrap: anywhere stops long URLs from overflowing on phones.

CSS Responsive Typography Syntax

Responsive type

:root {
  --step-0: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
  --step-2: clamp(1.5rem, 1.1rem + 2vw, 2.25rem);
  --step-4: clamp(2.25rem, 1.4rem + 4vw, 3.75rem);
}
body { font-size: var(--step-0); line-height: 1.6; }
h1 { font-size: var(--step-4); line-height: 1.1; text-wrap: balance; }
.prose { max-width: 65ch; }

CSS Responsive Typography Summary

  • Use rem for font sizes so text follows the reader's settings.
  • clamp(min, rem + vw, max) makes fluid sizes that still respond to zoom.
  • Keep text columns to about 60ch to 75ch wide.
  • Use unitless line heights: around 1.6 for body text and 1.2 for headings.
  • text-wrap: balance tidies headings; pretty tidies paragraph endings.

CSS Responsive Typography Examples

Each example runs in the page. Edit the code and press Run to see what changes.

Example 1

A fluid type scale

Drag the result panel wider and narrower. The headings scale smoothly.

:root {
  --step-0: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
  --step-2: clamp(1.4rem, 1.1rem + 1.5vw, 2rem);
  --step-4: clamp(1.9rem, 1.2rem + 3.5vw, 3.25rem);
}

.prose { font-family: Georgia, serif; font-size: var(--step-0); line-height: 1.6; }
.prose h1 { font-size: var(--step-4); line-height: 1.1; margin: 0 0 0.4em; text-wrap: balance; }
.prose h2 { font-size: var(--step-2); line-height: 1.2; margin: 1em 0 0.3em; }
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Lines 1 to 5The scale is defined once as variables.
  2. Line 7Body text grows only slightly between phones and desktops.
  3. Line 8The main heading changes the most, with tight line height and balanced lines.
Example 2

Readable line length

div { font: 17px/1.6 sans-serif; padding: 10px; margin-bottom: 10px; border-radius: 8px; }
.wide { background: #fee2e2; }
.limited { background: #dcfce7; }

.limited p {
  max-width: 60ch;
}
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 6The paragraph is never wider than about 60 characters, whatever the screen size.
Example 3

balance and pretty wrapping

Narrow the panel to see the difference in the headings.

h2, p { font-family: sans-serif; max-width: 420px; }
h2 { font-size: 1.6rem; line-height: 1.15; }

.plain { color: #9ca3af; }
.balanced { text-wrap: balance; }
.nice { text-wrap: pretty; line-height: 1.6; }
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 4Normal wrapping fills each line, which can leave one short word on the last line.
  2. Line 5Balanced wrapping makes lines a similar length.
  3. Line 6Pretty wrapping avoids a single orphaned word.

Common CSS Responsive Typography Mistakes

Pixel font sizes everywhere

Don't
body { font-size: 16px; }
h1 { font-size: 40px; }
Do
body { font-size: 1rem; }
h1 { font-size: 2.5rem; }

Pixel sizes ignore the reader's preferred font size.

vw-only font sizes

Don't
h1 { font-size: 5vw; } /* tiny on phones, huge on monitors, ignores zoom */
Do
h1 { font-size: clamp(2rem, 1rem + 4vw, 3.5rem); }

Line height with units

Don't
body { line-height: 24px; } /* headings inherit 24px and overlap */
Do
body { line-height: 1.5; }

A unitless value is multiplied by each element's own font size.

CSS Responsive Typography in Real Projects

Typography on real sites

Publications such as The Guardian and Medium keep article text around 65 to 70 characters wide with generous line height. Design systems define fluid type scales with clamp(), often generated by tools like Utopia. Chrome and Firefox support text-wrap: balance, and many blogs now use it on headings. Accessibility audits test text at 200% zoom, and sites using rem pass easily.

CSS Responsive Typography Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Keep the paragraph to about 65 characters per line.

.prose {
  max-width: 65;
}
Multiple choiceeasy

Why use rem for font sizes?

Multiple choicemedium

Which line height suits body text best?

Multiple choicemedium

What does text-wrap: balance do?

Fix the bugmedium

The heading should use clamp() between 2rem and 3rem, the paragraph should use a unitless 1.6 line height, and lines should be at most 60ch. Fix it.

.t { font-size: 6vw; }
.b { line-height: 26px; max-width: 900px; }
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Heading uses clamp between 2rem and 3rem
  • Heading size is within limits
  • Unitless line height
  • Lines limited to 60ch

CSS Responsive Typography Quiz

5 questions to check what you learned.

  1. What is 1.5rem with the default browser font size?

    • 15px
    • 1.5px
    • 24px
    • 32px
  2. Why add rem to a vw value in clamp's middle value?

    • Because vw doesn't work alone
    • So text still grows when the reader zooms or changes their font size
    • To make it smaller
    • For older browsers
  3. What is a comfortable line length for body text?

    • 20 to 30 characters
    • 150 characters
    • As wide as the screen
    • About 60 to 75 characters
  4. Why should line-height usually be unitless?

    • Units aren't allowed
    • It's faster
    • Each element multiplies it by its own font size
    • It removes spacing
  5. What does text-wrap: pretty improve?

    • Avoiding a single word left alone on a paragraph's last line
    • Heading font weight
    • Letter spacing
    • Underline style

CSS Responsive Typography Challenge

A readable article

  1. Set .article font-size: 1rem and line-height: 1.6
  2. Limit .article to max-width: 65ch
  3. Give .article h1 a font-size of clamp(2rem, 1.2rem + 3vw, 3rem), line-height: 1.1 and text-wrap: balance
.article { font-family: Georgia, serif; }
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • 1rem body text with 1.6 line height
  • Max width of 65ch
  • Fluid heading within limits
  • Tight balanced heading