LCP image size
The LCP element: transfer size and natural / rendered pixel size.
At a glance the headline numbers for LCP image size
The LCP element: transfer size and natural / rendered pixel size.
Distribution & median INP site count and median INP at each level of LCP image size — natural mp
Passing INP by LCP image size — natural mp which level passes the INP most often
LCP image size — natural mp 0.2 MP. p75 0.7 MP. p99 7.7 MP. At the low end (0–0): INP 99ms. At the high end (2+): INP 100ms. computed
Distribution & median INP site count and median INP at each level of LCP image size — rendered mp
Passing INP by LCP image size — rendered mp which level passes the INP most often
LCP image size — rendered mp 0.1 MP. p75 0.2 MP. p99 1.0 MP. At the low end (0–0): INP 99ms. At the high end (1+): INP 103ms. computed
Why this matters for the Core Web Vitals, and where to start fixing it
Three numbers describe the LCP image: the bytes over the wire, the pixels in the file, and the pixels actually shown. The gap between the last two is pure waste. An image with far more natural pixels than rendered pixels shipped resolution nobody saw, and the extra bytes stretched the load time.
Right-size first, then compress, then pick the format. Resizing the image to what is displayed saves more than recompressing a wrong-sized original ever will.
Chrome field data from 189,915 sites, representing millions of real page loads. How we measured.
Live queries (5) — admin only
SELECT COUNT(*) AS count,
quantile_disc(m.lcp.size.bytes, 0.10) AS p10,
quantile_disc(m.lcp.size.bytes, 0.25) AS p25,
quantile_disc(m.lcp.size.bytes, 0.50) AS p50,
quantile_disc(m.lcp.size.bytes, 0.75) AS p75,
quantile_disc(m.lcp.size.bytes, 0.90) AS p90,
quantile_disc(m.lcp.size.bytes, 0.99) AS p99
FROM sites WHERE m.lcp.size.bytes IS NOT NULL;
SELECT COUNT(*) AS count,
quantile_disc(m.lcp.size.natural_mp, 0.10) AS p10,
quantile_disc(m.lcp.size.natural_mp, 0.25) AS p25,
quantile_disc(m.lcp.size.natural_mp, 0.50) AS p50,
quantile_disc(m.lcp.size.natural_mp, 0.75) AS p75,
quantile_disc(m.lcp.size.natural_mp, 0.90) AS p90,
quantile_disc(m.lcp.size.natural_mp, 0.99) AS p99
FROM sites WHERE m.lcp.size.natural_mp IS NOT NULL;
SELECT CASE WHEN m.lcp.size.natural_mp >= 0 AND m.lcp.size.natural_mp < 1 THEN 0 WHEN m.lcp.size.natural_mp >= 1 AND m.lcp.size.natural_mp < 2 THEN 1 WHEN m.lcp.size.natural_mp >= 2 THEN 2 END AS bucket_idx, COUNT(*) AS n,
quantile_disc(crux."phone".inp, 0.5) AS median,
COUNT(*) FILTER (WHERE crux."phone".inp IS NOT NULL AND crux."phone".inp <= 200) * 1.0 / NULLIF(COUNT(*) FILTER (WHERE crux."phone".inp IS NOT NULL), 0) AS good_pct
FROM sites WHERE m.lcp.size.natural_mp IS NOT NULL GROUP BY bucket_idx;
SELECT COUNT(*) AS count,
quantile_disc(m.lcp.size.rendered_mp, 0.10) AS p10,
quantile_disc(m.lcp.size.rendered_mp, 0.25) AS p25,
quantile_disc(m.lcp.size.rendered_mp, 0.50) AS p50,
quantile_disc(m.lcp.size.rendered_mp, 0.75) AS p75,
quantile_disc(m.lcp.size.rendered_mp, 0.90) AS p90,
quantile_disc(m.lcp.size.rendered_mp, 0.99) AS p99
FROM sites WHERE m.lcp.size.rendered_mp IS NOT NULL;
SELECT CASE WHEN m.lcp.size.rendered_mp >= 0 AND m.lcp.size.rendered_mp < 1 THEN 0 WHEN m.lcp.size.rendered_mp >= 1 THEN 1 END AS bucket_idx, COUNT(*) AS n,
quantile_disc(crux."phone".inp, 0.5) AS median,
COUNT(*) FILTER (WHERE crux."phone".inp IS NOT NULL AND crux."phone".inp <= 200) * 1.0 / NULLIF(COUNT(*) FILTER (WHERE crux."phone".inp IS NOT NULL), 0) AS good_pct
FROM sites WHERE m.lcp.size.rendered_mp IS NOT NULL GROUP BY bucket_idx;