Skip to content
fontstay.dev
Source code on GitHub

fontstay.dev

View
Guide lines
measuring…

Stop the page from jumping when your font loads

Browsers show text in a fallback font first, then swap in your web font. If the two differ in size, lines wrap differently and the page jumps (layout shift, which Google measures as CLS). fontstay builds a fallback that matches your font's metrics, so the swap moves nothing.

Without tuning, the lines re-wrap and the content moves. With the tuned fallback, everything stays put.

No web font yet: the article uses the system font stack. Choose a font or drop a file anywhere.

Field notes · №7 · Typography & performance

Why the page jumps when a font loads

A web font arrives a moment after the text is first painted. Until then the browser shows a fallback, and when the real font takes over, every line can change its width and every block its height.

  • Glyph width

    Every typeface sets its letters at a different width, so the same sentence wraps at a different word.

  • Line height

    The font’s own ascent and descent and the line-height rule decide how much room a line takes.

  • Vertical metrics

    Ascent, descent and line gap live in the font file; a substitute with other numbers shifts the baseline.

  • Scripts and fallbacks

    Characters missing from the web font come from another family, which can make one line taller than its neighbours.

What moves, and why

Take a plain paragraph. In the fallback font it fills four lines; in the web font the same words need five. Everything below slides down by one line: that is a layout shift.

Width is only half of the story. Each font carries its own ascent, descent and line gap. With line-height: normal the browser builds the line box from them, so another font means another height even at the same size.

Inline elements add their own pressure: a bold run, an italic phrase, a superscript2 or a symbol such as ™ may come from another face and stretch the line it sits on.

Headings are the most visible victims. A large title that jumps by a few pixels drags the whole article with it, which is why headings and body text deserve separate fallbacks.

Text can also be re-balanced. Modern text-wrap: balance and text-wrap: pretty change where lines break, so test with and without them.

The cure is boring and effective: scale the fallback with size-adjust and give it the web font’s vertical metrics with ascent-override, descent-override and line-gap-override.

The best layout shift is the one nobody notices.
— a rule of thumb

A checklist for the next release

  1. Pick the fallback per system, not one for everybody.
  2. Compare regular, bold and italic faces separately.
  3. Test long and short lines, and with text-wrap on.
  4. Check scripts you do not read: Arabic, Japanese, Cyrillic.

Where a line gets its height

CauseEffect
Font sizeScales every metric
line-heightOverrides the font’s own metrics
Ascent and descentSet the content area of the line
Fallback glyphsCan raise a single line
Superscript and subscriptPush the line box up or down

Special characters

& © ® ™ § ¶ † ‡ • … – — « » “ ” ‘ ’ № € £ ¥ ¢ % ‰ ° ± × ÷ ≈ ≠ ≤ ≥ ∞ √ π → ← ↑ ↓ ½ ¼ ¾ ¹ ² ³ ℃ fi fl

@font-face {
  font-family: "Brand Fallback";
  src: local("Arial");
  size-adjust: 104.5%;
  ascent-override: 92%;
  descent-override: 24%;
}
body {
  font-family: "Brand", "Brand Fallback", sans-serif;
}
Set in two typefaces: the headings and the text come from different families. Switch the view above to compare the web font with its adjusted fallback.

Overlay: filled text is the web font, outlined dotted text is the adjusted fallback.