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.

What each approach actually costs, mechanism by mechanism.
Approach Extra requests Third-party data sent Ongoing maintenance
Google Fonts (linked)2+ (CSS host, font host)Visitor IP, to GoogleNone — Google serves updates
Self-hosted webfont1+ per weight/style loadedNoneManual: subsetting, WOFF2 conversion, cache headers
System-font stack0NoneNone

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:

This site's real CSS custom properties for type.
Property Value
--font-sans-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif
--font-monoui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace
@font-face rules in this codebase0

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.

This isn't a universal recommendation. A brand with a distinctive typeface as part of its identity has a real reason to accept the request cost a custom webfont brings. The point here isn't "system fonts are always correct" — it's that the request cost is real and worth deciding on deliberately, not defaulting into via a copy-pasted <link> tag from a design template.

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:

What's actually established about web font loading.
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

  1. Self-host it if avoiding third-party requests and their GDPR exposure matters for your audience — serve the WOFF2 files from your own origin.
  2. 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.
  3. 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.
  4. 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.
Curious what else on this site is measurably real vs. just claimed? The CSP hash worked example does the same thing for security headers — this site's own code, not a hypothetical.

Badri Dutta

Software engineer · 15 years building for the web

Fifteen years building for the web. This piece exists because most font-loading advice treats "just self-host it" as the whole answer and skips the option of not shipping a webfont at all — which is what this site's own CSS actually does.

Full background →