Yellow Theme

Next start · October 2026

Notes / 17

2026-09-15

Late font faces still swap after paint

We preloaded the webfonts and set font-display: block on every face. A hard refresh still flashed fallback bold and italic after first paint.

Thesis: Block is for the Latin faces that paint in the first viewport. Every late face — italic, latin-ext, extra weights — must be optional, or the browser will replace text that already rendered.

What we shipped first

The marketing chrome looked correct once the network settled. On a hard refresh, titles and body painted in the system fallback, then snapped into Cinzel and EB Garamond. Definition terms and <strong> jumped faces last. Lighthouse called the late swap; operators called it a flash.

We had treated font-display: block as “always show the brand font.” Preload helped the three first-paint files. It did not stop italic and mono files that arrived after paint from swapping glyphs already on screen.

The working shape

Only the first-paint Latin faces use block: Cinzel 700, EB Garamond 400, and JetBrains Mono 400. Every other face is optional — including italic and latin-ext. EB Garamond keeps size-adjust: 119% so a late optional face does not reflow Georgia’s x-height. Do not preload the optional files.

/* First-paint Latin faces — block so hard refresh paints the webfont */
@font-face {
  font-family: "Display";
  font-weight: 700;
  font-display: block;
  src: url("/assets/fonts/display-700.woff2") format("woff2");
}

@font-face {
  font-family: "Body";
  font-weight: 400;
  font-display: block;
  size-adjust: 119%; /* match fallback x-height; late swap must not reflow */
  src: url("/assets/fonts/body-400.woff2") format("woff2");
}

@font-face {
  font-family: "Mono";
  font-weight: 400;
  font-display: block;
  src: url("/assets/fonts/mono-400.woff2") format("woff2");
}

/* Late faces — optional so they never replace text that already painted */
@font-face {
  font-family: "Body";
  font-style: italic;
  font-weight: 400;
  font-display: optional;
  size-adjust: 119%;
  src: url("/assets/fonts/body-400-italic.woff2") format("woff2");
}

Checklist

Related: analytics that wait for a click (or eight seconds). How we deliver: methodology.

Engineering commentary only — not audit, legal, or certification advice.