Every guide to improving LCP arrives at the same instruction: find the
image that paints your first screen, and make the browser load it first. Preload it. Give
it fetchpriority="high". Stop lazy-loading it.
The instruction assumes something it never states — that the browser can find the image at all. The preload scanner, the part of the browser that races ahead to fetch resources early, works on one thing only: the markup the server sent. Not the DOM after JavaScript runs, and not stylesheets.
Resources that aren’t present in markup provided by the server on the initial navigation request can’t be discovered by the preload scanner.
We can measure how often that assumption holds, because we run a filter that does the job automatically. On every proxied site it scans the top of the document for a content image worth prioritising, and it writes down what it found. So we read 261 sites’ worth of those notes.
What the filter found
| Outcome | Sites | Share |
|---|---|---|
| A real above-the-fold content image, prioritised | 165 | 63% |
| No content image — only the logo could be prioritised | 24 | 9% |
| Nothing eligible at all | 72 | 28% |
On 96 of 261 sites — 37% — the standard advice has no object. There is no hero image in the served HTML for the browser, or for us, to load first.
The 24 in the middle row are the vivid ones. Those pages do have an image the browser can discover early, and it’s the logo in the header. The largest thing on the first screen — the photograph, the product shot, the video poster — is somewhere the preload scanner cannot look.
Then the finding split in two
The obvious next question is which sites those are. The answer stopped the article we were originally going to write.
| Platform | Sites | No discoverable hero |
|---|---|---|
| Duda | 49 | 2% |
| Wix | 29 | 21% |
| WooCommerce | 32 | 34% |
| Squarespace | 36 | 36% |
| Bitrix | 28 | 43% |
| WordPress | 24 | 46% |
| Webflow | 30 | 50% |
| Next.js | 16 | 100% |
Read that table naively and it says Squarespace has a hero problem a third as bad as Next.js’s. It doesn’t. We went back to the stored original HTML of every site in the “nothing found” group and looked for a priority hint the site had set on its own — because our filter deliberately skips an image that already carries one. There is nothing to fix on a page that already did the fixing.
So the 96 sites are two populations wearing the same symptom:
- Nothing to do. The platform generates the first screen as server-side markup and marks the hero as high priority. Duda, Squarespace and Wix are mostly here. Their share in the table above is an artefact of our filter having no work left, not of a slow page.
- Nothing to find. The first screen is assembled after the HTML arrives, or the hero lives in CSS, or it’s lazy-loaded into invisibility. Next.js, Webflow and self-built WordPress and Bitrix themes are here, and this is the group where the LCP element is genuinely undiscoverable at the moment it matters.
What it isn’t
We expected the CSS background image to be the explanation. A hero set with
background-image: url(...) is a perfectly valid LCP element — web.dev lists it among the
candidates — and it is invisible to the preload scanner, which “scans markup” and
“doesn’t scan other resource types, such as CSS”.
It explains nothing here — and it fails in the direction we didn’t expect. An above-the-fold CSS background was detected on 52% of the sites where a hero image was found, and only 26% of the sites where none was. For the explanation to work it needed to run the other way. CSS backgrounds are simply how a large part of the web builds first screens, on the pages where the hero is discoverable just as much as on the pages where it isn’t.
That 26% carries a floor we should name: our background detector reads the served markup too. A page that ships an empty container and builds its first screen afterwards gives it nothing to find either — so some of that number is the same blindness measured twice, not a statement about how those sites are built.
We’re stating the null result because the tidy version — “your hero is a CSS background, that’s why it’s late” — is the version we believed going in, and it’s the version that would have been easiest to write.
What this means if you’re trying to fix LCP
The first question isn’t which preload to add. It’s whether the browser can see your hero at all. Open your page’s source — the actual HTML the server sends, not the inspector’s DOM, which shows you the page after JavaScript has rewritten it:
- If the hero
<img>is there with a realsrc: you’re in the 63%. Addfetchpriority="high", removeloading="lazy"if it’s on there, and you’re done. This is the case every guide is written for. - If it’s there but lazy-loaded: the preload scanner reads
src, notdata-src— a deferred image “isn’t discovered earlier”. You’ve hidden your own LCP element. See lazy loading. - If it isn’t there at all — the markup has a container and a script — no preload hint
will help, because there’s nothing yet to hint at. The fix is architectural: server-render
the first screen, or ship the hero as a plain
<img>outside the framework’s hydration path. - If it’s a CSS background: the scanner can’t reach it. Send the hint out of band, in an
HTTP
Link:header, or add a matching<link rel="preload" as="image">to the document head.
How we measured it
Every number here comes from our own audit base: 261 sites, each fetched and processed by the same filter chain, with each applied patch and its reason recorded. Sites built on Tilda are excluded because they run a different filter set and would not be comparable. Every audit in the sample was created after 2026-07-17 — the date our pipeline began recording the pre-processing phase, so an older audit would silently under-report and is left out rather than mixed in.
“Discoverable” means our detector’s rules, listed in full in the caveats above: a real
<img> in the above-the-fold region, not a data URI, not named like a logo, not already
lazy-loaded, not already prioritised, and at least 200×100 where the page declares
dimensions. A genuine hero that trips one of those rules counts against us, which makes 37%
a ceiling on the problem rather than a precise count.
Method and limits
261 audited sites, each processed by the same reverse-proxy filter that looks for an above-the-fold image to preload at high priority. We read the filter's own patch logs: whether it prioritised a real content image, fell back to prioritising only the site logo, or found nothing eligible at all. Tilda sites are excluded because they run a different filter set, and every audit predates the base's filter-logging change on 2026-07-17, so all logs are directly comparable. For the sites where the filter found nothing, we then went back to the stored copy of the original HTML and checked whether the site already set fetchpriority="high" itself — which turns "no hero found" into "no hero to find" for a large share of them.
Measured on 26 Jul 2026 across 261 sites. These figures are frozen at that date — we don't quietly restate a published study when the audit base grows.
What this doesn't show
- This is not a random sample of the web. These are 261 sites we chose to audit — competitors, publishers, and platform batches assembled to study specific site builders. Read every figure as "of these 261 sites", never as "of the web". The platform mix in particular is deliberate, so the overall 37% is a property of our sample, not a measurement of the internet.
- "Discoverable" is defined by our detector's rules, not by the browser's. It requires an <img> in the above-the-fold region with a source that isn't a data URI, isn't named like a logo or icon, isn't already lazy-loaded, isn't already carrying a priority hint, and is at least 200x100 where dimensions are declared. A real hero that breaks one of those rules is counted as "not found". This makes the 37% an upper bound on the problem, not a precise count of missing heroes.
- A hero delivered as a CSS background image counts as "no <img> found" here, and CSS backgrounds are a legitimate LCP element. We checked whether that explains the split and it does not — an above-the-fold CSS background was detected on 26% of the sites where no hero was found against 52% where one was, the opposite of the direction the explanation needs. That comparison has a floor of its own, though: a page whose first screen is not in the served HTML offers our background detector nothing to find either, so part of that 26% is the same blindness rather than a fact about the sites.
- The fetchpriority check looks for the attribute anywhere in the served HTML, not specifically on the largest element. A site that prioritises some other image would be credited here as having done the work. It is a conservative check in the direction of making our own finding smaller.
Sources
- Largest Contentful Paint (LCP) — web.dev, Google
LCP reports the render time of the largest image, text block, or video visible in the viewport, relative to when the user first navigated to the page.
- Largest Contentful Paint (LCP) — web.dev, Google
An element with a background image loaded using the url() function, (as opposed to a CSS gradient)
- Don't fight the browser preload scanner — web.dev, Google
A preload scanner's role is speculative, meaning that it examines raw markup in order to find resources to opportunistically fetch before the primary HTML parser would otherwise discover them.
- Don't fight the browser preload scanner — web.dev, Google
Remember that the browser preload scanner scans markup. It doesn't scan other resource types, such as CSS which may involve fetches for images referenced by the background-image property.
- Don't fight the browser preload scanner — web.dev, Google
Resources that aren't present in markup provided by the server on the initial navigation request can't be discovered by the preload scanner.