Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Web fonts

In the lesson "Text and fonts" fonts came from the reader's device. If you need a special font the reader does not have, its file is put on the site and connected. Such a font is called a web font: the browser downloads it together with the page.

The @font-face rule

@font-face declares a font: what name to give it and where the file lives. Each style — regular, bold, italic — gets its own rule with the same name:

@font-face {
  font-family: "Inter";
  src: url("fonts/inter-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
}
 
@font-face {
  font-family: "Inter";
  src: url("fonts/inter-bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
}
 
body { font-family: "Inter", sans-serif; }

Now font-weight: 700 takes the second file. The woff2 format is a compressed font for the web: it is several times lighter than older formats and understood by every modern browser, so other formats are no longer needed.

The name is yours

font-family inside @font-face is just a name you make up. The local() function takes a font from the device, so this example works without downloading any files:

<style>
  @font-face {
    font-family: "Headings";
    src: local("Georgia"), local("Times New Roman");
  }
  h2 { font-family: "Headings", serif; }
</style>
 
<h2>A heading in the "Headings" font</h2>
<p>Regular text in the default font.</p>

The browser tries the sources from src in order and takes the first one available.

While the font loads: font-display

The font file does not arrive at once. The font-display property inside @font-face decides what to show meanwhile:

ValueWhat happens
swapthe fallback font at once, then swapped for the real one
blockup to 3 seconds of invisible text, then the real font
fallbacka short pause, and if the font is late, the fallback stays
optionalthe font only if it arrived almost instantly

For text, swap is the usual choice: the reader sees the words at once instead of a blank page.

Variable fonts

Usually each style is a separate file. A variable font keeps all weights in one file, and you can pick any, even 550. In @font-face the range is given as font-weight: 100 900. The system font of many devices is variable too — if yours is, each line is bolder than the one before:

<style>
  p { font-family: system-ui, sans-serif; font-size: 20px; margin: 4px 0; }
</style>
 
<p style="font-weight: 200;">Weight 200</p>
<p style="font-weight: 350;">Weight 350</p>
<p style="font-weight: 550;">Weight 550</p>
<p style="font-weight: 800;">Weight 800</p>

Such fonts may have other axes — smoothly adjustable parameters, such as letter width. They are controlled with font-variation-settings: "wght" 550, "wdth" 80. But for weight the regular font-weight is more convenient.

Google Fonts

In the fonts.google.com catalog you pick a font and get ready code for <head>. The preconnect lines open a connection to the font servers in advance, so the file arrives sooner:

<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@100..900&display=swap" rel="stylesheet">

wght@100..900 asks for the whole variable font, and display=swap is the same as font-display: swap. Then in CSS you write font-family: "Inter", sans-serif.

Self-hosting or a CDN

A CDN is someone else's server that hands out files, like Google Fonts. It is the easiest way to add a font, but the browser goes to another site, and a third party sees the visit. You can download the font files and put them next to your site — this is self-hosting. It does not depend on a foreign server, and in Europe it is often chosen for privacy. Either way, keep a fallback list: font-family: "Inter", system-ui, sans-serif.

Common mistake

The path in url() is relative to the CSS file, not to the HTML page. If the styles are in css/style.css and the fonts in a fonts folder next to css, the path url("fonts/inter.woff2") points to a non-existent css/fonts/:

my-site/
├── index.html
├── css/
│   └── style.css    ← url("../fonts/inter.woff2")
└── fonts/
    └── inter.woff2

The browser silently shows the fallback font. You can check whether the file loaded in the Network tab of the developer tools.

Thanks for reading!

Donate to the site — we work hard for you.