Fallback font metric mismatch causes reflow
Aliases: font metric mismatch · size-adjust · swap reflow · fallback metrics
What it is
A fallback face and a web font can share a declared size and still disagree on advance width, x-height, ascent, and line gap. When the swap runs, the text block’s used width and line-box height change, and neighbors are pushed. That reflow is font metric mismatch, not the flash form itself. During FOIT the glyphs may be invisible while boxes still lay out to some metrics; during FOUT the reader is already looking at fallback, and the swap frame reflows those lines. The layout shift comes from the metric delta, not from “a different face appeared.”
Why it happens
Layout consumes glyph advance, and the ascent/descent/line-gap of the line box—not the font’s name. Fallback is usually a system Latin or a generic CJK face whose width table will not match a branded web font. The same string then wraps at different points and the block height jumps. size-adjust, ascent-override, descent-override, and line-gap-override retune the web font toward the fallback, or the reverse, so the two layouts’ line boxes nearly agree and the swap is almost a repaint.
Without those overrides, a swap is a new constraint set. CLS will count the text block’s movement. Loading strategy only decides whether the user sees the swap; visibility does not cancel the metric delta. optional with no swap leaves the delta latent; once a swap happens, metric mismatch is the direct cause of reflow.
Studying it
In the lab, record line boxes and overflow for the same text node before and after swap: render one string in both faces, compare width, line count, and block height, then apply size-adjust and see if the delta collapses. In the field, attribute layout-shift sources on text nodes whose timestamp sits near a FontFace going loaded. Labs often hit cached fonts; first field visits still swap, so the two metric mismatch—low lab CLS, jumping field text. Do not treat a lab session with warm font cache as a first visit.
Where it stops holding
Tabular figures and icons that are SVG rather than a font do not use this width table. If the user has set a default face whose metrics already sit close to the web font, the delta shrinks. font-display: optional with a miss never does a second layout, so the mismatch stays silent. Vertical writing uses a different metric axis; horizontal size-adjust does not transfer. Print that composes only the final face never goes through a fallback swap.
Applying it
- Pick a fallback stack per
@font-face, measure width and line height of the same key copy in both faces, and writesize-adjustplus ascent/descent overrides until line count no longer changes on swap. - For non-wrapping labels and buttons, reserve the wider of the two faces in the container, not only override metrics.
- Mixed CJK and Latin need separate fallback tuning; one
size-adjustwill not fit both. - Verify on a cold load: the block’s bottom edge should not move on the swap frame.
layout-shiftentries attributed to text nodes should vanish once overrides are in effect.