Web Fonts
Prerequisites: Fonts and typography
Web fonts let you use typefaces that aren't installed on the visitor's device.
@font-face
@font-face {
font-family: "Inter";
src: url("/fonts/InterVariable.woff2") format("woff2");
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Inter";
src: url("/fonts/InterVariable-Italic.woff2") format("woff2");
font-weight: 100 900;
font-style: italic;
font-display: swap;
}
body {
font-family: "Inter", system-ui, sans-serif;
}
- Use WOFF2 — compressed and supported everywhere. You don't need older formats anymore.
- Several
@font-facerules with the same family name describe different weights and styles of one family. - Serve fonts from your own site when you can (no extra connection, no privacy concerns), and check the font's license.
font-display
What happens while the font downloads:
| Value | Behavior |
|---|---|
swap |
Show fallback text immediately, swap when the font arrives |
fallback |
Brief invisible period, short swap window, then keep the fallback |
optional |
Use the font only if it's available almost immediately |
block |
Hide text up to ~3 seconds — avoid for body text |
swap is a good default for brand fonts; optional avoids layout shifts
entirely.
Reducing layout shift
When the web font replaces the fallback, text can reflow. Match the fallback's metrics with an adjusted local font:
@font-face {
font-family: "Inter Fallback";
src: local("Arial");
size-adjust: 107%;
ascent-override: 90%;
}
body { font-family: "Inter", "Inter Fallback", sans-serif; }
(The right percentages depend on the fonts; tools such as Capsize and framework font helpers compute them.)
Variable fonts
One file contains a continuous range of weights (and sometimes widths, slant, or optical sizes):
h1 { font-weight: 750; }
.condensed { font-stretch: 80%; }
.custom { font-variation-settings: "opsz" 32; }
Usually smaller than loading four or five static weights.
Loading faster
- Preload the one or two most important fonts:
<link rel="preload" href="/fonts/InterVariable.woff2" as="font" type="font/woff2" crossorigin>(see the HTML course). - Subset fonts to the characters you need (
unicode-rangesplits a family by script). - Use fewer families and weights. System font stacks load instantly.
Icon fonts
Prefer inline SVG icons to icon fonts: they're sharper, accessible with proper labeling, and don't fail as a row of empty boxes when the font doesn't load.