01 — Purpose

Typography without blocking content

Fonts affect rendering speed, layout stability, readability, and perceived performance.

Custom typography is branding — but every font file is a network request that can delay text and shift layout when metrics swap. Typography should not gate access to content.

This site self-hosts a minimal set — see the performance standard fonts section for the approach we ship here.

02 — Principles

Readable content beats decorative type

Users should read the page — not wait for the perfect weight to arrive.

  • limit families and weights — each file adds latency and cache cost
  • system font stacks are valid defaults for body text
  • subset when possible — ship only the scripts and glyphs you need

03 — Practice

Loading fonts responsibly

Preload sparingly; display sensibly.

  • font-display: swap (or optional) so text shows while fonts load
  • preload only critical above-the-fold faces — over-preloading competes with LCP assets
  • self-host or serve from your CDN — avoid third-party font chains when you can
  • match fallback metrics (size-adjust, ascent-override) to reduce CLS when web fonts swap in
@font-face {
  font-family: 'DM Sans';
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/dm-sans-400.woff2') format('woff2');
}

04 — Avoid

Font loading anti-patterns

More weights is not more design system.

  • loading six weights and two families on every page “just in case”
  • render-blocking CSS that imports fonts from slow third-party hosts
  • giant variable fonts when two static weights would suffice
  • invisible text during load (font-display: block) on body copy

05 — Close

Count the files

If you cannot name every font request on your critical path, you have too many.

Audit Network tab on a cold load. List families, weights, and transfer size. Cut until the typography still meets design intent — then measure LCP and CLS again.

Related: Core Web Vitals, design tokens for typography variables.