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 Name | Ratio | Sizes (base 16px) | Best For |
|---|---|---|---|
| Minor Second | 1.067 | 16, 17, 18, 19, 21 | Subtle hierarchy, long-form content |
| Major Second | 1.125 | 16, 18, 20, 23, 25 | Body-heavy pages, documentation |
| Minor Third | 1.200 | 16, 19, 23, 28, 33 | General purpose, most websites |
| Major Third | 1.250 | 16, 20, 25, 31, 39 | Marketing pages, presentations |
| Perfect Fourth | 1.333 | 16, 21, 28, 38, 50 | Bold 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.