A late font should not move the page

When a web font arrives late, the text is set twice and the page can jump. We measured the jump on our own pages, and what eight CSS rules did to it.

The text is set twice

A web font takes time to arrive. Until it does, a browser can hide the text, or it can set the text at once in a font the device already has and set it again when the web font arrives. We ask for the second (font-display: swap). You can start reading before everything has loaded.

The cost is that no two fonts are the same width. A paragraph that took six lines in the first font takes seven in the second, and everything under it moves down while you are reading.

Google calls that movement a layout shift. It adds the shifts of a page into a score, Cumulative Layout Shift, which is one of its three Core Web Vitals. A score of less than 0.1 counts as good.

A stand-in of the same size

CSS can describe a stand-in: a font the device already has, scaled to take up the same room as the font that is on its way. CSS calls it a fallback font.

@font-face {
  font-family: 'Spectral Fallback';
  src: local('Times New Roman');
  font-weight: 400;
  size-adjust: 109.74%;
  ascent-override: 96.5%;
  descent-override: 42.19%;
  line-gap-override: 0%;
}

body {
  font-family: 'Spectral', 'Spectral Fallback', serif;
}

size-adjust makes the stand-in as wide as the real font. The three overrides give it the same height above and below the line. While Spectral is on its way, the text is set in Times New Roman at 109.74% of its size. When Spectral arrives, every line is already the length it is going to be.

Where 109.74 comes from

We did not try values until it looked right. We set the same text in both fonts and compared the two lengths.

The text is this site’s own: every word of its case studies and service pages, 40,407 characters. A font file says how far each letter advances, and which pairs of letters sit closer together. We applied those rules the way a browser does and added up the line. In Spectral the text takes 0.4392 of the font size per character. In Times New Roman it takes 0.4002. The first divided by the second is 1.0974.

Three things turned up on the way.

The average of a language is not the average of your text. Our first attempt used a table of how often each letter occurs in English. For our sans-serif it gave 105.76%. Measured on the site’s real words, with their capitals, figures and punctuation, the answer is 103.81%.

Capitals need their own stand-in. The title on our home page is set in capitals, and capitals have other proportions than running text: 91.54% against 103.81%. With one stand-in for both, the full stop at the end of the title jumped 115 pixels to the left on a 1440-pixel screen when the font arrived. The title now has a stand-in measured on its own word.

Each weight is a different font. Spectral Light is narrower than Spectral Regular, 0.4311 against 0.4392, so it has its own rule. Our sans-serif turned out to be the opposite case. We set one line in five weights, from 300 to 800, and it came out 2,889 pixels long every time. One rule covers all of them.

That makes four stand-ins. Android has other system fonts than the rest, so each one is written twice: eight rules.

What it changed

We held every font back by 350 milliseconds, loaded each page, and let the browser report its own layout shifts. “Before” is the same build with the eight rules taken out.

Page Screen Before After
Home desk 0.0200 0.0000
Technical SEO desk 0.0453 0.0000
Case study desk 0.0032 0.0000
About desk 0.0449 0.0000
Home phone 0.0093 0.0000
Technical SEO phone 0.0212 0.0001
Case study phone 0.0197 0.0000
About phone 0.0043 0.0000

Measured on 30 September 2026 in Chromium 153 on Linux. “Desk” is a window of 1440 by 900 pixels, “phone” one of 390 by 844. Each figure is the middle one of three loads. A load counted only if the text was on screen before the first font arrived.

None of the “before” figures would have failed Google’s test. The largest is 0.0453, and the limit is 0.1. We did not do this to pass. We did it because a page that moves under the reader looks careless, and because the fix is eight short rules.

What it does not fix

The letters still change shape. The lines hold, but for a moment the text is in another typeface. We prefer that to hiding the text.

Single words still differ. A scale can only match on average. “SEO” is about four pixels wider in the stand-in than in the real font. In a paragraph the differences cancel out. In a three-letter label they do not.

Safari applies only part of it. size-adjust has worked in Safari since version 17. The three height overrides have not shipped in a released Safari; MDN lists them as preview only. There the width matches and the text may sit a little higher or lower in its line until the font arrives.

Most of this is not measured on real devices. Only Chromium reports layout shifts, so there is no figure for Safari or Firefox at all. The figures above come from a desktop Linux machine, with the letter-snapping that Linux applies switched off, because phones and Macs do not do it. With it switched on, the “after” figures were between 0.0000 and 0.0002. The rules for Android are calculated from its system fonts and have not been checked on a phone.

Look at your own site

Open your site in Chrome. Open DevTools, go to the Network panel, tick “Disable cache”, set the throttling to a slow connection and reload. Watch the text during the first second. If the lines re-break and the page jumps, this is the cause. The Performance panel shows the same thing as a track named “Layout shifts”.

If it jumps, the work is small: one measurement for each font, and one rule for each result.

Technical SEO

What a search engine reads on a page

Every page carries a second set of facts, written for machines: title, description, canonical, robots, headings, links. What each one does, in Google’s words.

Website performance

Why our tables say “Not measured”

A number without a date and an instrument is only a claim. What can be measured the day a site goes live, what needs visitors, and what only the owner can see.