← All writing
Craft · · 8 min

Cumulative Layout Shift

Three numbers published by somebody with no stake in the argument, which changes the politics of this work far more than it changes the engineering.

Performance SEO

A client’s marketing manager stopped in the middle of a status call last week to say their own site had done the thing where it jumps, and that they’d hit the wrong link because of it.

They weren’t reporting a bug. They were on their phone looking for the page we were talking about, the layout moved under their thumb somewhere between the look and the tap. They landed on a promo banner instead of the product. They mentioned it the way you’d mention traffic on the way in.

I have been putting that exact behavior into audit documents for that client since 2018. Screenshots of it happening, a description of what causes it, a list of the elements doing it. It has never once come back with a decision attached.

Google had published three numbers a few days earlier, and one of them measures precisely the thing that had just happened to them.

Three numbers

At a high level, the metrics are how long the main content takes to appear, how long the page takes to respond to the first tap, and how much the layout moves around while it loads. They’ll feed into search ranking at some point next year.

None of that changes the engineering advice. Everything I’d have told you to do in April is what I’d tell you to do in May. I get to point somewhere different now while I’m saying it.

Largest contentful paint is when the biggest thing above the fold actually showed up. Not when the server answered, not when the DOM finished, but when the visitor saw the thing they came for. Under 2.5 seconds is the line. It’s the one that finally answers “our time to first byte is great,” which somebody has said to me in a meeting while being completely correct.

First input delay is the gap between somebody tapping and the page reacting. In practice it measures how busy the main thread is with parsing and executing, which makes it the third-party problem I spent last November measuring with a threshold attached to it.

Cumulative layout shift is how much of the page moved while it was loading. That’s the one from the call.

Nobody had a word for it

Layout shift is the first performance metric I’ve seen that measures something every single person has experienced and nobody outside this job had a name for.

You go to tap a link. An ad loads above it. The link moves. You tap the ad.

Everybody has done that. Everybody has done it one-handed, walking, on a page they were halfway to leaving anyway. And until this month there was no number on it. So it wasn’t on anybody’s list, so it got fixed in the places where a developer happened to care enough to fix it quietly.

Naming a thing is most of the work of getting it fixed. I keep running into that well outside of performance work, on problems that were cheap and available to fix the whole time and just didn’t have a handle anybody could grab. The checkout autofill we broke over the winter had a name and a specification behind it and still went six weeks, because the form looked completely fine the whole time.

It’s also the cheapest of the three to do something about, and most of the doing is reserving space for things that arrive late.

the four fixes
<!-- 1. dimensions back on the images, so the browser can reserve the
     right aspect ratio before the file arrives -->
<img src="hero.jpg" width="1200" height="675" alt="…">

<!-- 2. reserve the box for anything injected later: ads, embeds, banners -->
.ad-slot { min-height: 250px; }

<!-- 3. font-display: swap plus a preload of the body font, so the swap
     happens early instead of a second in -->
<link rel="preload" href="/fonts/body.woff2" as="font" type="font/woff2" crossorigin>

<!-- 4. never insert anything above content somebody is already reading -->
HTML

The width and height one is worth stopping on, because it’s a funny reversal. We all stripped those attributes out years ago on the grounds that sizing belongs in the stylesheet, which was true then and is true now. Browsers have since started reading the two numbers to figure out an aspect ratio and hold the space before a byte of the image arrives, so an attribute we deleted for good reasons turned into the fix for a problem we caused by deleting it. Put them back, keep max-width: 100%; height: auto in the CSS, and nothing else has to move.

It’s fast on my machine

The change I keep thinking about isn’t in the three metrics. It’s in where the numbers come from.

They’re measured on real visitors, on the devices and connections those visitors actually have, and reported at the 75th percentile. Not a lab run on a wired connection. Not your laptop, which is the fastest computer that will ever load this site.

Which quietly removes the oldest defense in the business. “It’s fast on my machine” has ended a thousand conversations, it’s usually true, and it has never been relevant. A client now gets shown what happened to their own customers on their own phones, and a quarter of those customers had it worse than the number says.

The flip side is that one of the three can’t be measured in a lab at all. Input delay needs a real person to input something. Lab tools hand you total blocking time instead, which correlates closely enough to work from. It’s worth knowing the two are different so you don’t get caught quoting a lab score to somebody with the field data open.

Whose number it is

The evidence was never the problem. I’ve had good evidence for years.

The problem, I think, is that it was mine. Produced by me, about my own part of the work, pointing at somebody else’s tools. I caught myself doing the same thing in a rebuild proposal last December, which built its entire case out of things I could count on my own and none of it out of what using the site was actually like. “The front end developer thinks we should have fewer marketing scripts” is not a neutral finding. I’d be skeptical of it too if I were the one being asked to give up the chat widget.

So the conversation had one shape every time. I say the site is slow and here’s what I think it costs. Marketing says the widget books demos and here’s what they think that’s worth. Neither claim can be checked in the room, both of us sound confident. It gets settled by whoever is more senior or spoke most recently.

Nobody in those meetings was wrong, either. The widget really does book demos, the banner really does move stock, and the person defending them had no way to weigh a worry of mine against a figure they could see in a dashboard. I had a Lighthouse score and a feeling. They had revenue.

An outside body with a threshold on it changes that completely, and not because Google is wise. It’s because Google has no stake in the argument happening in that particular room, and because the client already cares enormously about what it thinks.

Two ways I expect this to go badly

Optimizing for the score. All three can be gamed, and my sense is there’ll be a whole cottage industry doing it by fall. You can improve the paint number by making the largest element smaller. You can hold the shift number near zero with a skeleton screen that reserves space for content that then takes five seconds to arrive, and the metric will look beautiful while the page gets worse to use. Where the metric and the experience disagree, the metric is wrong.

Performance becoming an SEO task. That’s the real cost of a search company owning this. It gets filed under search, it lands with whoever writes the meta descriptions, and it turns into a monthly report instead of a constraint on the design. It is a constraint on the design. The decisions that cost you these numbers get made by designers and marketers months earlier, in rooms with no developers in them, which is the whole reason to write the budget down as a number before anybody opens a design file.

Cheering for the referee

I don’t love how this happened. A search company decided what the web measures itself by, everybody rearranged their year around it inside a week, and the fact that I agree with the three things it picked is mostly luck. If the third number had been something dumber we’d all be chasing that instead, with the same enthusiasm. I’d rather say that out loud than pretend it away.

But I’ve spent the whole time I’ve been doing this making the case with numbers I produced myself, and losing politely to people with better numbers about other things. Next month I get to pull up field data for the client’s own domain, about their own customers, and let it say the thing I’ve been saying since 2018. The marketing manager already knows exactly what it feels like. Now there’s a page that agrees with them.

Read similar posts
8 min

Let the browser measure it

A site built last year with a perfectly good image pipeline was still sending the 1600px file to a phone, and it turned out to be the same missing attribute I wrote a whole post about in 2018.

8 min

Three years and two weeks

Three years of asking for the same performance work, getting agreed with in meetings, and never getting it scheduled. Then their new operations director asked whether the website had a carbon footprint and the identical list was approved in 2 weeks.