Google Fonts adds at least two extra requests, from separate hosts, and carries a documented GDPR ruling against unconsented use in one jurisdiction. Self-hosting removes the third-party request but adds manual maintenance. A system-font stack removes both, at the cost of giving up a chosen typeface — the option this site's own CSS confirms it uses.
Key takeaways
- Google Fonts is at least two extra requests, not one — a CSS file from fonts.googleapis.com, then the actual font files from fonts.gstatic.com, each a fresh DNS lookup and connection.
- A German court ruled unconsented Google Fonts embedding breaches GDPR (LG München I, January 2022) because it sends the visitor's IP address to Google's servers. One jurisdiction, one ruling — not a universal legal fact, but the reason self-hosting became a common recommendation afterward.
- font-display: swap controls the visible symptom (FOIT vs FOUT), not the underlying request cost — it changes how the wait looks, not whether the wait happens.
- Self-hosting removes the third-party request but not the font-loading cost itself, and adds the ongoing job of managing WOFF2 files and subsets yourself.
- This site ships zero font requests — a checked fact from its own CSS, not a claim. That's this article's actual worked example.
Three options, not two
Most write-ups frame this as Google Fonts vs. self-hosted webfonts, which skips the option that actually removes the network cost entirely: a system-font stack, where the CSS lists the fonts most operating systems already ship — San Francisco on Apple platforms, Segoe UI on Windows, Roboto on Android — and lets the browser pick whichever one the visitor's device already has installed. No request, no download, no FOIT or FOUT, because there is nothing to wait for.
| Approach | Extra requests | Third-party data sent | Ongoing maintenance |
|---|---|---|---|
| Google Fonts (linked) | 2+ (CSS host, font host) | Visitor IP, to Google | None — Google serves updates |
| Self-hosted webfont | 1+ per weight/style loaded | None | Manual: subsetting, WOFF2 conversion, cache headers |
| System-font stack | 0 | None | None |
This site's own font stack, checked not claimed
Rather than describe a hypothetical system-font stack, here's the one actually shipping in this site's own assets/css/main.css:
| Property | Value |
|---|---|
| --font-sans | -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif |
| --font-mono | ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace |
| @font-face rules in this codebase | 0 |
Every visitor sees whichever font their own device already had installed for that stack — which is also why this page looks slightly different depending on whether you're on macOS, Windows or Android. That's the actual trade: no request, no third-party data transmitted, no font-loading flash to engineer around, in exchange for not controlling exactly which typeface every visitor sees.
Documented vs. inferred vs. unsupported
Font-loading advice online mixes settled browser mechanics with folklore about exact millisecond costs that were never actually measured on the page making the claim. Graded honestly:
| Claim | Status | Basis |
|---|---|---|
| Google Fonts requires a separate CSS request, then a separate font-file request | Documented | Directly observable in the network panel of any browser's dev tools on any page using it |
| Unconsented Google Fonts embedding breaches GDPR | Inferred | One documented court ruling (LG München I, Jan 2022) in one jurisdiction; not a settled global legal standard |
| Self-hosting fonts is always faster than Google Fonts' CDN | Unsupported | Depends on the visitor's cache state, geography and connection — stated as a blanket rule far more often than it's actually measured |
| font-display: swap causes a specific number of milliseconds of layout shift | Unsupported | Shift magnitude depends on the fallback and webfont metrics on the specific page; no fixed figure applies generally |
If you do use a webfont anyway
- Self-host it if avoiding third-party requests and their GDPR exposure matters for your audience — serve the WOFF2 files from your own origin.
- Set font-display: swap (or optional if a layout shift on swap is worse than staying in the fallback) so text is never invisible while the font loads.
- Subset the font file to only the character ranges and weights you actually use — a full family file is usually far larger than the subset a Latin-only site needs.
- Preload the font file with <link rel="preload" as="font"> if it's used above the fold, so the browser doesn't discover it late via the CSS.