CSS Custom Fonts
In this page:
@font-face {
font-family: "CustomName";
src: url("font-file.woff2") format("woff2");
}
selector {
font-family: "CustomName", fallback-family;
}
The @font-face Rule
@font-face defines a new custom font family by pointing to one or more font files and giving that family a name you can then reference like any other font-family value. It's declared once, usually near the top of a stylesheet, before any selector uses the name it defines.
- Accepted values:
- @font-face — declares a custom font
- font-family — the name you choose
- src — url("file.woff2") format("woff2"), or local() for an installed font
- font-display — auto | block | swap | fallback | optional
- font-weight | font-style — which variant the file provides
- unicode-range — the characters the file covers
Example: The @font-face Rule
<style>
@font-face {
font-family: "MyFont";
src: url("myfont.woff2");
}
p {
font-family: "MyFont";
}
</style>
<p>Uses the custom font family defined above</p>
Font File Formats
Modern browsers mainly need WOFF2 (smallest, best compression) with a WOFF fallback for slightly older browsers; TTF/OTF are rarely needed for the web today. Listing multiple src formats in one @font-face block lets the browser pick the first format it actually supports.
Example: Font File Formats
<style>
@font-face {
font-family: "MyFont";
src: url("myfont.woff2") format("woff2"),
url("myfont.woff") format("woff");
}
</style>
<p>Browser picks the first format it supports</p>
font-weight and font-style in @font-face
A single font family often ships as several separate files, one per weight/style combination (regular, bold, italic). Each variant needs its own @font-face block with matching font-weight/font-style values so that later using font-weight: bold on an element correctly selects the bold file instead of fake-bolding the regular one.
- Accepted values:
- normal | bold — keywords
- 1 to 1000 — numeric weights, usually 100 to 900
- a range — e.g. 100 900 for variable fonts
- font-style: normal | italic | oblique
Example: font-weight and font-style in @font-face
<style>
@font-face {
font-family: "MyFont";
src: url("myfont-bold.woff2");
font-weight: bold;
}
strong {
font-family: "MyFont";
}
</style>
<strong>Loads the real bold file, not a fake bold</strong>
Fallback Stacks for Custom Fonts
Because a custom font file must download before it can render, always list a similar-looking system font (or a generic family like sans-serif) after it in font-family, so text stays legible during that brief loading window or if the download fails entirely.
Example: Fallback Stacks for Custom Fonts
<style>
p {
font-family: "MyFont", Arial, sans-serif;
}
</style>
<p>Falls back to Arial while MyFont loads, or if it fails</p>
font-display and Loading Behavior
The font-display property (e.g. swap) controls what happens to text while a custom font is still downloading — swap shows the fallback font immediately and swaps in the custom font once ready, avoiding invisible text and improving perceived performance.
- Accepted values:
- auto — browser decides (initial value)
- block — invisible text briefly, then swap
- swap — fallback font at once, swap when loaded
- fallback — very short block, short swap
- optional — the browser may skip the font
Example: font-display and Loading Behavior
<style>
@font-face {
font-family: "MyFont";
src: url("myfont.woff2");
font-display: swap;
}
</style>
<p style="font-family: 'MyFont', sans-serif;">Fallback shows immediately, swaps once ready</p>
- Pointing
srcat a wrong file path, so the font silently falls back to the default font. - Not giving a fallback font in
font-family, so text looks wrong while the file loads. - Using a
font-weightin the element that has no matching font file, so the browser fakes a bold.
Supported in all modern browsers: Chrome, Firefox, Safari, Edge and Opera.
Chapter Quiz — Complete all 10 topics to unlock
0/10 topics done
Complete these topics first: