Typography and web fonts

CSS · Essentials · 10 min

Text is most of what users read; good type settings matter more for readability than any other styling.

Most of a page is text, and a handful of properties control it.

  • font-family takes a stack: "Inter", system-ui, sans-serif. The browser uses the first available font, and the generic family at the end is the final fallback. system-ui uses the operating system's interface font, which looks native and loads instantly.
  • font-size in rem; font-weight from 100 to 900 (400 normal, 700 bold); font-style: italic.
  • line-height unitless, around 1.4 to 1.6 for body text. Unitless values are multiplied by each element's own font size; a value like 24px would be inherited as a fixed size and squash larger headings.
  • letter-spacing, text-transform, text-align, text-decoration.
  • max-width: 65ch keeps lines readable.

Web fonts are declared with @font-face, giving a family name, a src URL (use WOFF2, the compressed standard format) and the weights and styles the file covers. A variable font covers a whole weight range in one file: font-weight: 100 900.

font-display: swap shows fallback text immediately and swaps in the web font when it loads, instead of hiding text for up to three seconds. Self-host fonts or preload the critical one, and limit yourself to a couple of families and weights; each file is a separate download.

clamp() gives fluid type: font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem) grows with the viewport between a minimum and maximum. Keeping a rem term in the middle value means it still responds to user zoom.

Example

@font-face {
  font-family: "Inter";
  src: url("/fonts/InterVariable.woff2") format("woff2");
  font-weight: 100 900;          /* variable font: one file, all weights */
  font-display: swap;
}

body {
  font-family: "Inter", system-ui, sans-serif;
  font-size: 1rem;
  line-height: 1.5;              /* unitless: scales with each element */
  color: #222;
}

article { max-width: 65ch; }

h1 {
  font-size: clamp(1.75rem, 1.2rem + 2.5vw, 3rem);  /* fluid heading */
  font-weight: 750;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

Remember

  • Always end a font stack with a generic family
  • Use unitless line-height
  • WOFF2 + font-display: swap for web fonts
  • clamp() gives fluid sizes with limits

Watch out for

  • Setting line-height in px on body, so big headings inherit a cramped fixed line height.

Check yourself

  1. Why is line-height: 1.5 usually better than line-height: 24px on body?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@font-face