Web Development
How to Add Custom Fonts to Your Website with CSS @font-face
Adding a custom font to a website comes down to two steps: tell the browser where to find the font file, then apply it to your text. There are two main paths — using a hosted service like Google Fonts, or self-hosting the files yourself. This guide covers both, with code you can paste in today.
Method 1: Google Fonts (the quick way)
Google Fonts hosts the files for you, so you only need to add a <link> to your HTML <head> and reference the family in CSS. Pick your weights, then embed the link:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">Then apply it in CSS:
body {
font-family: 'Inter', system-ui, -apple-system, sans-serif;
}Note the &display=swap parameter — it tells the browser to show fallback text immediately and swap in the web font when it loads, which prevents invisible text. The preconnect links shave latency by opening the connection to Google's font servers early.
Method 2: Self-hosting with @font-face
Self-hosting gives you full control, better privacy, and often better performance because the files come from your own domain. Download the font in WOFF2 format (the smallest, best-supported web format), place it in your project, and declare it with @font-face:
@font-face {
font-family: 'My Brand Sans';
src: url('/fonts/my-brand-sans.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'My Brand Sans';
src: url('/fonts/my-brand-sans-bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}Declare each weight and style as its own @font-face block, all sharing the same font-family name. The browser then picks the right file based on the font-weight and font-style you request:
body {
font-family: 'My Brand Sans', system-ui, sans-serif;
}
h1 {
font-weight: 700;
}Build a bulletproof fallback stack
Never list just one font. Always provide fallbacks so text stays readable while your web font loads (or if it fails). A good modern stack ends with the system UI font and a generic family:
/* Sans-serif stack */
font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
/* Serif stack */
font-family: 'Lora', Georgia, 'Times New Roman', serif;
/* Monospace stack */
font-family: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;Choose a fallback with similar metrics (x-height and width) to your web font to minimize the visible "shift" when the swap happens.
Variable fonts: one file, many weights
A variable font packs an entire range of weights, widths, or slants into a single file. Instead of loading separate Regular, Medium, and Bold files, you load one and access any value via CSS:
@font-face {
font-family: 'Inter var';
src: url('/fonts/Inter-variable.woff2') format('woff2');
font-weight: 100 900; /* the supported range */
font-display: swap;
}
h1 { font-weight: 820; } /* any value in range */Variable fonts often reduce total download size when you use three or more weights, and they unlock fine-grained control over typography.
Common mistakes to avoid
- Loading too many weights. Every weight and style is a separate download. Load only what you use.
- Forgetting `font-display`. Without it, browsers may hide text for up to three seconds (a "flash of invisible text").
- Skipping fallbacks. A single-font stack leaves users staring at nothing if the font is slow or blocked.
- Using outdated formats. TTF and EOT are large and legacy. WOFF2 is the modern standard.
For a deeper dive into making fonts fast, read our guide to web font performance and Core Web Vitals. Not sure which font to add in the first place? Identify it from any image with our AI Font Finder.
Spotted a font you love?
Upload any image and let our AI identify the typeface in seconds — free, no sign-up.
Try the AI Font Finder