The font swap and layout shift.
The font swap is the browser painting text first with a fallback family and replacing it when the real font arrives — and if the two families occupy different space, it produces layout shift.
Until web fonts download, text either stays invisible or is painted with a fallback family. The second is almost always the right choice — invisible text is the worst user experience and directly delays LCP too. But the swap has a price: if the two families’ letter widths differ, the text reflows and everything below it shifts.
This is the most insidious source of layout shift because on a fast connection it barely shows. The developer tests on their own machine, the font arrives instantly, no shift occurs. On a slow connection the swap becomes visible — and surfaces in the field data.
Metric matching
The fix is bringing the fallback family close to the real family’s metrics. Modern browsers offer adjustable properties for this: the fallback font’s size ratio, ascent and descent can each be tuned. Tuned correctly, the two families occupy the same height and nothing shifts at the swap.
The values are not guessed but measured: the real font and the fallback are rendered side by side with the same text and their heights compared. The difference converts into the adjustment value. This measurement is done once and stays valid as long as the font does not change.
An alternative is preloading the font as a critical resource — with no swap there is no shift. But that puts the font at the head of the render chain and can delay LCP. The choice between the two approaches depends on whether text is the LCP element on that page.
The case on this site
This topic entered here not as theory but as a measured case — and what the case taught was the opposite of what was expected.
The font loading behavior was suspected as a source of layout shift, and a fix was intended. The planned change looked reasonable and was a known best practice. It was measured before being applied.
The measurement showed the shift did not come from there. The font swap was producing no shift, because the fallback family was metrically matched; the shift came from elsewhere — from a section pinned during scrolling. Had the planned change been applied, it would have broken a working arrangement and delayed finding the real problem.
The measurement did not fix a bug — it prevented a wrong fix.
After the case a guard was added, and its logic is deliberately reversed: the font is DELIBERATELY delayed, and the heading height is measured to stay FIXED on four separate routes. The test simulates the font never arriving and proves the layout does not break. Metric matching stopped being a setting configured once and forgotten; it became a contract verified on every run.
How many families, how many weights
Every additional font family means an additional request, an additional wait and an additional swap risk. The family count is therefore a performance budget item and must be decided at the design stage.
On this site the budget is limited to two families, and the verification suite measures it. Both are variable fonts — a single file carries all weights and widths. In the classic approach every weight would be a separate file, and six weights would mean six requests.
The variable font’s second advantage is on the design side: with a continuous width axis, intermediate values become usable. This site’s signature effect uses exactly that axis — at no extra file cost.
One subsetting note: font files should be produced with only the needed character set. A file limited to Latin and extended Latin is many times smaller than one carrying the full Unicode range — and for Turkish content, those two sets are exactly what is needed.
The swap behavior options
There is a setting that tells the browser what to do while the font is awaited, and its four values offer different trade-offs. The default behavior hides the text briefly, then paints with the fallback and swaps when the real font arrives.
- Swap — paint immediately with the fallback, replace when the real font arrives. Best for LCP, highest CLS risk.
- Fallback — a short blocking window, then the fallback; if the real font arrives late, it is never used.
- Optional — a short blocking window, then it STAYS on the fallback. No shift risk, but the design may look inconsistent.
- Block — hide the text. Directly delays LCP; right in almost no situation.
The right choice depends on whether the fallback family is metrically matched. If it is, swap is safe and gives the best result; if not, the optional behavior prevents the shift entirely but the design never shows for some users. Once metric matching is in place, the trade-off disappears — both are won.
Hosting: keep it on your own server
Pulling fonts from a third-party provider was standard practice for a long time and is largely a mistake today. The reason sits on both the performance and the privacy side: a request to an external domain means an extra DNS resolution and an extra connection setup — and since browser caches are now partitioned by domain, the assumption “it was already downloaded on another site” no longer holds.
On the privacy side, every request reports the user’s address to a third party. In some jurisdictions this counts as a data transfer requiring explicit consent.
Hosting on your own server solves both problems at no extra cost: the file will be downloaded anyway; only where it is downloaded from changes. On this site both font families are served from the site’s own domain, subsetted and in variable versions — and the content security policy blocks external resource requests anyway.
A maintenance rule to close with: when the font changes, the metric matching values must be measured again. The fallback settings were computed against a specific real font; when the family changes, that computation becomes void and the shift silently returns. One more example of why settings configured once and forgotten must be bound to a test — the guard says the value went stale at the moment of the change.