AnyTool
Your files never leave your device. All processing happens locally in your browser.

How do I pair fonts for a website?

The Font Pairing Suggester gives you curated heading + body Google Fonts pairings, each with a one-line rationale, a live preview you can fill with your own text, and copyable @import + font-family CSS. Every pair follows the principle of “contrast with harmony” — the heading and body differ (serif vs sans, or a strong weight/scale jump) but share era, x-height or a common super-family so they feel intentional. Fonts load on demand for preview only; your text never leaves the browser, and a system-font-only mode makes zero network calls.

  • Use two families: one for headings, one for body — more than two rarely helps
  • Contrast them (serif↔sans, or a big weight/size jump) but keep a shared mood
  • Body text wants a legible face at 14–18px; headings can be more expressive at 36–72px
  • Copy the @import + CSS, or switch to a system-font stack for zero network use

What is

Font pairing (type pairing)

Font pairing is choosing two (occasionally three) typefaces that work together in one design — typically one for headings and one for body text. The guiding rule is “contrast with harmony”: the faces should be different enough to create a clear hierarchy (achieved through classification, weight or scale) yet share enough structural DNA (comparable x-height, similar historical period or mood, or membership of the same super-family) to feel deliberate rather than accidental. A reliable default is pairing a serif with a sans-serif, or two faces from the same designed family.

Web Design

Related terms

typographytypeface classificationserifsans-serifx-heightsuper-familytype hierarchyGoogle Fonts@font-facefont-display: swap

Frequently Asked Questions

No. Your specimen text, sizes and toggles stay on the page and are never uploaded or added to any request. The only network use is downloading the selected font files from Google for the preview, and that request contains just family names and weights.

The tool is client-side. Your heading and body specimen text, the size sliders and the light/dark and system-only toggles are just React state in your browser tab — they are never uploaded, logged, or included in any font request. To render a real specimen the page injects a Google Fonts <link> for only the families you select, so your browser fetches those font files from fonts.gstatic.com; that request carries the family names and weights in the URL (and, like any web request, your IP and user-agent), but no specimen text or personal data. Turning on “System fonts only” disables all font loading and previews with the OS font stack, so the tool then makes zero network calls beyond ads.

Contrast with harmony. Make the heading and body clearly different (serif vs sans, or a strong weight/scale jump) so the hierarchy reads, but keep a shared trait — similar x-height, the same era or mood, or the same super-family — so the pair feels intentional.

A good pairing balances contrast and harmony. CONTRAST creates hierarchy and visual interest: pair a serif heading with a sans-serif body (or vice versa), or jump the weight (a heavy display face over a regular text face), or the scale (large expressive titles over modest body copy). HARMONY keeps it cohesive: the two faces should share a comparable x-height, a similar historical period or personality, or belong to the same designed super-family (e.g. IBM Plex Serif + Plex Sans, or DM Serif Display + DM Sans). The most common beginner mistake is choosing two faces that are too SIMILAR — two nearly identical sans-serifs look like a mistake, not a pairing. Two families is almost always enough.

Loading Google Fonts from Google’s CDN sends every visitor’s IP address to Google, which a German court found can breach GDPR without consent. The compliant fix is to self-host the font files on your own domain so no visitor data reaches Google.

When a page loads Google Fonts from Google’s servers, each visitor’s browser sends its IP address (plus user-agent and referer) to Google to fetch the font files. Because GDPR treats IP addresses as personal data, a German court (Munich, 2022) ruled that embedding Google Fonts via Google’s CDN without consent can be unlawful. The standard remedy is to SELF-HOST: download the .woff2 files from Google Fonts (they are open-source under the OFL or Apache licence) and serve them from your own domain with a local @font-face rule, so no visitor data ever goes to Google. This tool previews via Google’s CDN for convenience and is honest about that; for production, self-host or use the system-font fallback.

Usually just two: one for headings and one for body text. That gives clear hierarchy without clutter. A third is occasionally useful for accents or code, but every extra family adds weight and slows the page.

For most sites, two font families is the sweet spot — one for headings and one for body copy — which delivers a clear hierarchy while keeping the design cohesive and the page light. You can create additional levels of hierarchy within two families by varying weight, size, style (italic) and letter-spacing rather than adding more typefaces. A third family is occasionally justified for a specific role (a monospace face for code, or a distinctive accent for pull-quotes), but each extra family and weight is another font file to download, so it costs performance. Requesting only the weights you actually use — as this tool does — keeps the payload small.

Detailed Explanation

Methodology

How the Font Pairing Suggester Works

A pure engine (fontPairingEngine.ts) holds a curated catalogue of heading + body Google Fonts pairings, each tagged with a mood and a one-line rationale. For the selected pair it builds a Google Fonts css2 request for ONLY those families and only the weights actually used, and serialises the copy-paste CSS — an @import line plus font-family declarations for headings and body — so the preview and the exported code match exactly. The React page injects a single <link> for the visible/selected families, lets the user type their own heading and body specimen text (kept entirely local), tune sizes, and toggle a dark canvas or a system-fonts-only mode.

  • Curated pairings, each with a mood tag and a plain-language rationale
  • Only selected families + used weights are requested — never the whole catalogue
  • Every font-family value ends in a system fallback so text is readable while loading
  • The exported @import URL is identical to what the preview loads
  • Pure, deterministic engine — the same pair always emits the same CSS
How It Works

The Pairing Principle: Contrast With Harmony

Good font pairing balances CONTRAST (so heading and body form a clear hierarchy) with HARMONY (so they feel intentional). Contrast is created by classification (serif vs sans-serif), weight (a heavy display face over a regular text face), or scale (large expressive titles over modest body copy). Harmony comes from shared traits: a comparable x-height, the same historical period or personality, or membership of the same designed super-family. Each suggestion in this tool names the specific relationship, so it teaches WHY a pair works rather than presenting arbitrary combinations.

  • Contrast via classification, weight or scale builds the hierarchy
  • Harmony via shared x-height, era, mood, or a common super-family
  • Super-family pairs (IBM Plex Serif + Sans, DM Serif Display + DM Sans) are guaranteed to harmonise
  • The biggest mistake is pairing two faces that are too similar
  • Two families is almost always enough; a third costs performance
Technical Details

On-Demand Font Loading and the System Fallback

Rather than shipping a giant stylesheet, the tool injects a Google Fonts css2 <link> for only the families in view, requesting just the weights it previews, with display=swap so text shows immediately in the fallback and swaps in when the web font arrives. Every generated font-family value ends in a robust system stack (e.g. -apple-system, Segoe UI, Roboto for sans; Georgia, Times for serif), so nothing is invisible while fonts load. A “System fonts only” switch removes the <link> entirely and previews with the OS stack, which is useful for a zero-dependency, offline, privacy-first baseline.

  • A single <link> is injected for only the selected/visible families
  • display=swap avoids invisible text (FOIT) during load
  • System fallback stacks are baked into every exported value
  • System-only mode removes the <link> and makes zero font requests
  • Requesting only used weights keeps the download small
Limitations

Honest Limitations: Google’s CDN and Rendering

To preview real type, the page fetches font files from Google’s CDN (fonts.gstatic.com), so Google can see the visitor’s IP address and user-agent for that request — a documented GDPR consideration (a 2022 Munich court ruling found consent-less Google Fonts embedding can be unlawful). No specimen text or personal data is sent; the request is only family names and weights. For production, self-hosting the open-source .woff2 files (OFL/Apache licensed) removes Google from the path entirely. The tool is also a suggester, not a guarantee: pairings should be tested with real content and languages, and font rendering (hinting, sub-pixel anti-aliasing) varies across operating systems and browsers.

  • Previewing via Google’s CDN exposes the visitor IP/user-agent to Google
  • A 2022 Munich court ruling flagged consent-less Google Fonts as a GDPR risk
  • Self-hosting the .woff2 files (OFL/Apache) removes Google from the path
  • Suggestions are curated by principle, not guaranteed — test with real content
  • Rendering varies by OS/browser; verify on real devices
Privacy & Security

Private by Design

Everything except font-file fetching happens on the user’s device. The pairing catalogue, the rationale and the exported CSS are computed locally in the browser tab; the specimen text, size sliders and toggles are just page state that is never uploaded, logged or added to any request. The only network use for the tool itself is downloading the selected font files for the live preview, and switching on “System fonts only” eliminates even that. Output is plain CSS copied to the clipboard, the tool works offline once cached (in system-only mode), and closing the tab discards all state.

  • Catalogue, rationale and CSS are computed entirely in the browser
  • Specimen text and settings are never uploaded or added to font requests
  • The only tool network use is fetching selected font files for preview
  • System-only mode makes zero font requests and works offline
  • No tracking, no accounts, no server-side storage
Ways to use web fonts, and where this tool fits
ApproachHow it loadsPrivacy / trade-off
Google Fonts via CDN (this tool’s preview)Browser fetches .woff2 from fonts.gstatic.com on demandFastest to set up; visitor IP goes to Google (GDPR consideration)
Self-hosted Google FontsServe downloaded .woff2 from your own domain via @font-faceNo data to Google; you manage the files and caching
System font stack (system-only mode)Uses fonts already on the device — no downloadZero network use and instant, but limited to installed faces
Variable fontsOne file spans many weights/widths via axesSmaller total payload for many weights; broad modern support

This tool previews via Google’s CDN for convenience and is explicit about it; for production, self-host the open-source .woff2 files or use the system-font fallback. Listed families are open-source (OFL or Apache). As of July 2026.