Cumulative Layout Shift (CLS) is often described as a “layout problem,” but in practice, it is frequently a font problem. This case study documents how a seemingly correct setup still produced a CLS score close to 1.0, and how fixing font metrics and layout stability reduced CLS to near zero without changing design or content.
The Problem: CLS Near 1.0 on Mobile
Lighthouse reported a CLS score of approximately 0.93 on mobile. The report pointed clearly to two main contributors:
-
Web fonts loaded from
fonts.gstatic.com -
Minor layout shifts inside a blog list and its cards
What made this case confusing was that best practices already appeared to be in place. Fonts were using font-display: swap, images had reasonable dimensions, and there were no obvious DOM insertions during load.
Despite this, the layout shifted dramatically once the fonts finished loading.
Why font-display: swap Was Not Enough
The key misunderstanding in many CLS cases is assuming that font-display: swap alone prevents layout shifts. In reality, it only ensures that text is visible early. It does not guarantee that the fallback font and the final font share the same metrics.
In this case, the fallback font had different ascent, descent, and line gap values compared to the final font. When the real font loaded, text height changed, pushing the entire blog list downward. Because this happened after initial rendering, Lighthouse recorded it as a large layout shift.
Diagnosing the Root Cause
The Lighthouse CLS breakdown highlighted .woff2 font files as the primary source of layout shifts. Enabling Layout Shift Regions in Chrome DevTools made the issue obvious: nearly the entire page moved when the web font replaced the fallback font.
This confirmed that the problem was not JavaScript or late content insertion, but font metric mismatch.
The Core Fix: Font Metrics Overrides
The most effective fix was adding font metrics overrides directly to the @font-face declaration. This forces the browser to treat the fallback font as having metrics similar to the final font.
A simplified example of the solution: