Web Typography: Font Selection and Readability Guide
Typography is the foundation of web design. Approximately 95% of web content is text, and the quality of typography determines how effectively that content communicates. Good typography is invisible — readers focus on meaning, not letterforms. Bad typography creates friction, increases cognitive load, and drives users away. Mastering typographic principles is the highest-leverage design skill for improving web quality. According to readability research, well-set typography can improve reading comprehension by up to 30% and reading speed by up to 12%.
Font Selection Strategy
Choosing the right typeface establishes your brand voice and reading experience. Serif typefaces (Merriweather, Georgia, PT Serif, Source Serif) excel for long-form reading with their bracketed serifs and connecting strokes that guide the eye along lines of text. Serif fonts are traditionally preferred for print but work equally well on high-resolution screens. Sans-serif typefaces (Inter, Roboto, Open Sans, SF Pro) provide clean, modern readability, particularly at small sizes on screens where their open counters and simple forms improve legibility.
Font pairing requires contrast with harmony. Contrast comes from structure — pair a serif heading typeface (Playfair Display) with a sans-serif body typeface (Inter), or the reverse. Harmony comes from shared proportions — x-height, cap height, ascender height, and stroke modulation should be similar between paired typefaces. Typeface super-families like Roboto (sans-serif) and Roboto Slab (serif) guarantee compatibility because they’re designed by the same type designer with matching proportions.
System font stacks eliminate web font loading entirely for instant text rendering. font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif renders in the user’s native system font — San Francisco on Apple devices, Segoe UI on Windows, Roboto on Android. System fonts load instantly, never cause invisible text (FOIT), and match the operating system aesthetic for a native feel.
Modular Type Scales
A modular type scale establishes consistent size relationships between text elements across the entire design system. Starting from a base size (typically 16px for body text), each step multiplies by a chosen ratio. A perfect fourth ratio (1.333) generates: 12px (caption), 16px (body), 21px (h4), 28px (h3), 38px (h2), 50px (h1), 67px (display). A major third ratio (1.25) generates smaller jumps: 14px, 16px, 20px, 25px, 31px, 39px, 49px.
Choose your ratio based on content density and information hierarchy. Dense content (news articles, documentation, data tables) benefits from smaller ratios (1.25 or 1.2) with more heading levels available for sub-sections. Sparse content (marketing pages, portfolios, landing pages) uses larger ratios (1.333 or 1.5) with dramatic size variation for visual impact. Adjust the scale responsively — mobile may compress to a 1.2 ratio for tighter screens, desktop expands to 1.333 for breathing room.
CSS custom properties implement type scales consistently across components. Define each step as a custom property: --text-sm: 0.875rem, --text-base: 1rem, --text-lg: 1.25rem, --text-xl: 1.5rem. Reference these variables throughout your stylesheet in every component. Changing the scale for responsive breakpoints requires updating only the variable definitions, ensuring system-wide consistency.
Line Height and Measure
Line height (leading) controls vertical spacing between lines of text. Body text should use 1.5–1.8 line height for comfortable extended reading on screens. Low line heights (under 1.4) cause descenders to clash with ascenders on the line below, reducing readability. High line heights (over 2.0) break the visual connection between consecutive lines, making it harder to follow the text flow. Headings use tighter line height (1.1–1.3) because larger type sizes need less vertical breathing room.
Measure (line length) determines readability — the width of a text column measured in characters per line. The ideal line length for body text is 45–75 characters, including spaces. The CSS ch unit simplifies measure implementation — max-width: 65ch sets the container width to 65 characters of the current font. Short lines (under 40 characters) cause excessive eye movement with too many line breaks. Long lines (over 90 characters) make it difficult for the eye to track from the end of one line to the start of the next.
Vertical rhythm creates consistent spacing throughout the document for visual harmony. Define a baseline grid — --baseline: 1.5rem — and space all elements in baseline increments using margin-bottom: var(--baseline). Headings, paragraphs, lists, blockquotes, and images all align to the baseline grid. The visual harmony of consistent vertical rhythm makes long-form content more readable and professional-looking.
Web Font Performance
Web fonts can significantly impact page load performance and user experience. Each font file adds an HTTP request and kilobytes of transfer — a typical web font package with regular, bold, italic, and bold-italic weighs 100-400 KB. The font-display CSS descriptor controls font rendering behavior during loading. font-display: swap shows fallback text immediately and swaps to the web font when loaded, preventing invisible text but causing a flash of unstyled text (FOUT). font-display: optional is even faster — the web font is used only if loaded before page rendering, providing instant text display.
Preconnect hints accelerate font loading by establishing early connections before the browser discovers the font CSS. <link rel="preconnect" href="https://fonts.googleapis.com"> and <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> establish early TCP and TLS connections to font servers. Subsetting fonts removes unnecessary characters — Latin subsets exclude Cyrillic, Greek, Vietnamese, and other character sets for Western-language sites, reducing file size by 50-70%.
Variable fonts provide multiple weights, widths, and styles in a single font file, replacing 10-20 individual weight files. One variable font file (typically 20-80 KB) replaces the entire typeface family. font-variation-settings: 'wght' 400, 'wdth' 100 controls weight and width axes programmatically. Variable fonts enable smooth weight transitions for animation, responsive typography that adjusts weight at different screen sizes, and dynamic text effects.
Establishing Typographic Hierarchy
Visual hierarchy guides readers through content, indicating what’s important and how information relates. Size is the primary differentiator — main headings are largest, through subheadings, to body text, to captions and footnotes. Weight adds emphasis within the same size — bold headings stand out from regular body text. Spacing creates grouping — related content has close spacing, different sections have generous spacing above.
Color and contrast further differentiate typographic levels. Dark headings on light backgrounds create maximum emphasis for main titles. Muted body text using a slightly lighter hue (like #4a4a4a instead of pure black #000) reduces visual weight for extended reading. Accent colors highlight links, pull quotes, and important information that needs attention. Consistent color assignment — all level-2 headings the same muted blue, all links the same brand color — creates predictable patterns.
Typographic hierarchy should be systematic rather than ad-hoc. Define heading levels with their sizes, weights, colors, line heights, and spacing in a design token system. Apply these tokens consistently across all pages using your CSS architecture. The system ensures that any content structure — from a simple blog post to a complex documentation page — communicates clearly.
Variable Fonts
Variable fonts encode multiple font styles (weight, width, slant, optical size) in a single file. They dramatically reduce page weight while providing unlimited intermediate styles. Use CSS font-variation-settings to control variation axes: font-variation-settings: 'wght' 500, 'wdth' 75. The font-weight property works when the weight axis is registered. Google Fonts and others provide variable font options. Variable fonts enable responsive typography that adjusts based on viewport or container size.
Font Loading Strategies
Control font loading to minimize layout shift and invisible text. Use font-display: swap for brand-critical text that must use the custom font, accepting a flash of unstyled text (FOUT). Use font-display: optional for body text — the browser uses the system font if the web font does not load quickly. Preload critical fonts with <link rel="preload">. Subset fonts to remove unused characters for smaller file sizes.
FAQ
What is the best font for web body text? Inter, Source Serif, Merriweather, and Open Sans are proven choices. The “best” font depends on your brand voice, content length, and target audience. Test fonts in context at actual sizes on actual devices.
How many fonts should I use on a single page? Maximum two typefaces — one for headings, one for body text. A single typeface family with multiple weights provides sufficient variation. Each additional typeface increases page weight and design complexity.
What is the difference between pt, px, em, rem, and ch? pt is a print unit (1/72 inch). px is a screen pixel. em is relative to the parent element’s font size. rem is relative to the root element’s font size (typically 16px). ch is the width of the “0” character in the current font. Use rem for spacing and sizing, ch for measure limits.
How do I handle Chinese, Japanese, or Korean typography? CJK typography has different rules. Line height should be 1.8–2.0. Measure should be 30–40 characters. Font size generally larger than Latin text. Use system fonts optimized for CJK.
Should I use web fonts or system fonts? Web fonts give you design control and brand expression. System fonts provide instant loading and native OS integration. Use web fonts for brand-critical headings; system fonts for body text where performance matters.
For more on frontend development, see our Sass CSS preprocessor guide and forms validation guide.