Typography for the Web: Fonts, Pairing & Readability

Typography is the most important design decision you'll make for any website. It affects readability, mood, trust, accessibility, and even conversion rates. Studies show that 95% of web design is typography — the text is what users come for, and how you present it determines whether they stay. Yet many designers treat font selection as an afterthought, defaulting to whatever looks nice without understanding the principles that make text truly readable.

This guide covers everything you need to master web typography: choosing and pairing fonts, sizing with modern CSS, optimizing line height and spacing, building type scales, loading fonts performantly, and ensuring accessibility.

Choosing the Right Font

The first decision is the font category. Each communicates a different personality:

  • Sans-serif (Inter, Roboto, Open Sans): Clean, modern, digital-first. Best for UI, dashboards, and tech products. Dominates web design today.
  • Serif (Merriweather, Lora, Playfair Display): Traditional, authoritative, literary. Best for long-form content, editorial sites, and luxury brands.
  • Monospace (JetBrains Mono, Fira Code, Source Code Pro): Technical, precise. Best for code blocks, data tables, and developer tools.
  • Display/Decorative: Unique, attention-grabbing. Use only for large headings and logos — never for body text.

For most websites, a well-chosen sans-serif handles everything. Inter (used on this site) was designed specifically for computer screens with features like contextual alternates and tabular figures built in.

Where to Get Fonts

Google Fonts is the most popular source — free, open-source, and easy to integrate. It serves over 1,500 font families to 60+ billion web pages monthly. Other excellent sources include Adobe Fonts (included with Creative Cloud subscriptions), Font Squirrel (curated free fonts), and Fontsource (self-hosted npm packages for Google Fonts).

Font Pairing Strategies

If you use two fonts, they need to complement each other. The golden rule: contrast with harmony. Fonts should look different enough to create visual hierarchy but share enough structural DNA to feel cohesive.

Proven Pairing Approaches

  • Serif headings + sans-serif body: The classic web pairing. The serif adds personality to headings while the sans-serif keeps body text clean. Example: Playfair Display + Source Sans Pro.
  • Same family, different weights: The safest approach. Use one font family (like Inter) with bold/heavy for headings and regular for body. Zero risk of clashing.
  • Superfamily pairing: Some type families include both serif and sans-serif versions designed to work together. Examples: Merriweather + Merriweather Sans, Roboto + Roboto Slab.

What to Match

When pairing fonts, compare these properties:

  • x-height: The height of lowercase letters. Fonts with similar x-heights look harmonious side by side.
  • Proportions: The width-to-height ratio of characters. Don't pair a condensed font with an extended one.
  • Stroke contrast: The variation between thick and thin strokes. High-contrast serifs pair well with low-contrast sans-serifs.

Sizing: rem, clamp(), and Type Scales

Font sizing on the web has evolved significantly. Here's the modern approach:

Use rem, Not px

The rem unit is relative to the root font size (the <html> element, typically 16px). Unlike px, rem respects the user's browser font-size preferences — critical for accessibility. If a visually impaired user sets their browser to 20px base size, rem-based text scales up automatically while px-based text stays fixed.

Set your base: html { font-size: 100%; } (equals 16px by default), then use rem throughout: h1 { font-size: 2.5rem; } = 40px at default.

Fluid Typography with clamp()

CSS clamp() creates responsive font sizes without media queries:

font-size: clamp(1rem, 2.5vw, 1.5rem);

This sets a minimum (1rem/16px), a preferred size that scales with viewport width (2.5vw), and a maximum (1.5rem/24px). The browser picks the middle value as long as it's between min and max. This single line replaces multiple media queries and produces smooth scaling.

Type Scale

A type scale is a set of harmoniously related font sizes. Instead of picking arbitrary numbers, multiply your base size by a consistent ratio:

Scale NameRatioSizes (base 16px)Best For
Minor Second1.06716, 17, 18, 19, 21Subtle hierarchy, long-form content
Major Second1.12516, 18, 20, 23, 25Body-heavy pages, documentation
Minor Third1.20016, 19, 23, 28, 33General purpose, most websites
Major Third1.25016, 20, 25, 31, 39Marketing pages, presentations
Perfect Fourth1.33316, 21, 28, 38, 50Bold hierarchy, hero sections

For most websites, a Minor Third (1.2) or Major Third (1.25) ratio works well — enough contrast between heading levels without extremes.

Line Height, Line Length, and Spacing

These three properties have more impact on readability than font choice itself:

Line Height (Leading)

Line height controls the vertical space between lines of text. WCAG 2.1 Success Criterion 1.4.12 recommends at least 1.5× the font size for body text. In practice:

  • Body text: 1.5 to 1.75 (sweet spot: 1.6)
  • Headings: 1.1 to 1.3 (tighter because headings are larger and shorter)
  • Small text / captions: 1.6 to 1.8 (wider because small text needs more breathing room)

Line Length (Measure)

The optimal line length for readability is 45–75 characters per line (including spaces). Lines that are too long cause reader fatigue — the eye struggles to track back to the next line. Lines that are too short create choppy reading with too many line breaks. For body text at 16px, this translates to roughly 600–800px max-width on the content container.

Letter Spacing and Word Spacing

Most well-designed fonts have optimal spacing built in. Adjustments are rarely needed for body text but useful for specific cases:

  • All-caps text: Add 0.05–0.1em letter-spacing. Uppercase letters are designed to sit next to lowercase — they look cramped when all caps without extra spacing.
  • Very large headings: Tighten letter-spacing slightly (-0.01 to -0.02em). Large text has naturally more visual space between letters.
  • Small text: Add slight letter-spacing (0.01–0.02em) for legibility at small sizes.

Font Loading and Performance

Web fonts are one of the most common performance bottlenecks. A single font file can be 50–200KB, and multiple weights multiply that. Here's how to load fonts without hurting Core Web Vitals:

font-display: swap

Always use font-display: swap in your @font-face declarations (or add &display=swap to Google Fonts URLs). This tells the browser to show text immediately in a fallback font, then swap to the web font once loaded. Without this, users see invisible text (FOIT — Flash of Invisible Text) while fonts download.

Preconnect and Preload

Add preconnect hints for external font services to start the connection early:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

For critical fonts (your body font), consider preload to fetch the file even earlier in the page load sequence.

Subset and Limit Weights

Only load the weights you actually use. Every additional weight is another 20–50KB. Most websites need at most: Regular (400), Medium (500) or SemiBold (600), and Bold (700). Google Fonts lets you specify exact weights in the URL to avoid downloading unused ones.

If your audience is primarily English-speaking, subset your fonts to include only Latin characters. This can reduce file size by 50–80% by excluding Cyrillic, Greek, Vietnamese, and other character sets.

Accessibility Checklist

Typography directly impacts whether your content is accessible to all users. Follow these WCAG-aligned guidelines:

  • Minimum 16px body text — anything smaller requires perfect vision. 18px is increasingly the standard.
  • Color contrast 4.5:1 minimum for normal text (WCAG AA). Use the Color Palette Extractor to verify.
  • Don't convey meaning through font alone — screen readers can't distinguish fonts. Use semantic HTML (headings, emphasis) instead.
  • Avoid justified text — the uneven word spacing creates "rivers of white" that hurt readability, especially for dyslexic readers.
  • Use relative units (rem) — so text scales with user preferences.
  • Paragraph spacing ≥ 2× font size (WCAG 1.4.12) — helps users with cognitive disabilities distinguish paragraphs.

Frequently Asked Questions

Stick to 2 fonts maximum — one for headings and one for body text. Using more than 2 creates visual noise, slows page load, and makes your design look unprofessional. Many successful websites use a single font family with different weights.
1.5 to 1.75 is the ideal line-height range for body text. WCAG 2.1 recommends at least 1.5× the font size. For headings, use 1.1–1.3. For small text, go wider at 1.6–1.8.
Use rem. Rem units respect the user's browser font-size preference, making them accessible. Set your base on the html element, then use rem throughout. For responsive typography, use CSS clamp() to scale smoothly between breakpoints.
Variable fonts are single files containing multiple weights, widths, and styles. Instead of loading separate files for Regular, Bold, and Italic, one variable font gives you every weight. Use them when you need 3+ weights — the file size savings are significant.
The key is contrast with harmony. Pair a serif heading font with a sans-serif body font. Look for fonts with similar x-heights but different personalities. Classic pairings: Playfair Display + Source Sans Pro, Merriweather + Open Sans, Montserrat + Lora.

Design Better Websites

Explore all 9 free browser-based design tools — resize images, generate gradients, extract palettes, and more.

Explore All Tools →