Fast on a phone: what actually moved the numbers
Four changes that did most of the work on mobile, including two that look like best practice and were making things worse.
Mobile performance advice is mostly a list of things to switch on. In our experience the wins come from finding the two or three things already on the page that are quietly expensive, and most of them look correct in the code.
Backdrop-filter is the most expensive thing on your page
Frosted-glass surfaces cost a full-screen repaint on every scroll frame. On iOS Safari that alone can hold a page below sixty frames per second no matter what else you fix. We disable it entirely below 768 pixels. Nobody has ever noticed the difference on a phone; the scroll is transparently smoother.
loading="lazy" does not always defer
A native lazy image only defers if the browser knows it is far from the viewport. If the section mounts before layout has placed it, the browser resolves the question as "near enough" and fetches immediately. We had a video strip and a portrait pair eleven screens down, both loading during first paint, both marked lazy and both behaving correctly by specification.
The fix is to gate the element on an intersection observer instead, so nothing is requested until the section genuinely approaches the viewport. On our own page that was 232 KiB and six Lighthouse points recovered from content nobody had scrolled to.
The loading spinner was the layout shift
Every case study on this site scored a cumulative layout shift of 0.546, which is a failing grade three times over. The cause was a lazy-loaded route whose loading fallback was a small spinner: the page rendered a 200-pixel placeholder, then replaced it with the real article, and everything below moved.
Loading that route eagerly costs 1.7 KB gzipped. The layout shift went to 0.001. A deferred chunk is not free if the space it will occupy is unknown.
Resize the images before they reach the repository
The least clever item on the list and usually the biggest. Two founder portraits arrived as 2 MB PNGs. At the size they actually render, re-encoded as WebP, they are 54 and 45 KB together: a 96% reduction with no visible difference. Client logos on this site were 200 KB each until someone measured them.
How to know it worked
Measure the same page before and after, on a throttled mobile profile, and keep the numbers. Every change above was justified by a pair of measurements rather than by a rule, and one of them, the eager route, is the opposite of the usual advice.
