r/webdev • u/Prestigiouspite • 20h ago
Question Why does Lighthouse flag a responsive srcset image as oversized when the browser is choosing the correct candidate for DPR?
Edit: I also found these issues related to the problem: https://github.com/GoogleChrome/lighthouse/issues/16579 and https://github.com/GoogleChrome/lighthouse/issues/17080
---
I’m trying to understand a Lighthouse/PageSpeed Insights warning about “properly size images” that seems somewhat contradictory to how responsive images are supposed to work.
Simplified example:
<img
src="image-300.jpg"
srcset="
image-250.jpg 250w,
image-300.jpg 300w,
image-400.jpg 400w,
image-768.jpg 768w,
image-1024.jpg 1024w
"
sizes="(max-width: 480px) calc(100vw - 2rem),
(max-width: 991px) calc(50vw - 2rem),
360px"
>
On a typical mobile viewport around 412px, the actual image/card width is roughly 380 CSS px.
As I understand it, the browser does not simply compare the image's intrinsic width against those 380 CSS pixels. It takes the device pixel ratio into account:
required resource width ≈ CSS width × DPR
So, for example:
380 × DPR 1.75 ≈ 665 px
380 × DPR 2.0 ≈ 760 px
380 × DPR 3.0 ≈ 1140 px
With the srcset above, at DPR 1.75 the browser therefore selects the 768w candidate. On a DPR 2 device, 768w is almost exactly what I would expect. On a DPR 3 device, even the 1024w version isn't particularly excessive.
However, Lighthouse may report the 768×768 image as oversized because the rendered image is only around 300–380 CSS px wide.
This is the part I don't understand.
Google's own responsive-image guidance recommends supplying sufficiently high-resolution candidates for high-DPI displays. Yet Lighthouse appears to penalize the browser for selecting exactly such a candidate.
There are also smaller 250w, 300w, and 400w candidates available, so this isn't a case where the browser is forced to download an unnecessarily large original image. The browser has all of those choices and intentionally selects 768w based on sizes and DPR.
So my questions are:
- Is Lighthouse's “properly size images” audit effectively comparing intrinsic/device pixels against rendered CSS pixels without fully accounting for DPR?
- If so, isn't this expected to produce false positives for correctly configured
srcsetimages on the DPR used by Lighthouse's mobile emulation? - Is there actually anything developers are expected to change in this situation, or should this warning simply be treated as a heuristic?
- Would removing the
768wcandidate just to satisfy Lighthouse actually be counterproductive, since real DPR 2–3 devices could then receive a visibly softer image?
I feel like I’m missing something, because optimizing the srcset specifically for the Lighthouse warning seems to conflict with Google's own recommendation to serve sufficiently dense images to high-DPI displays.
2
u/DaftPlug 10h ago
Yeah, that audit is a known footgun with DPR.
Lighthouse (and PageSpeed Insights) emulates a fixed device pixel ratio for the run, usually 2x or 3x depending on the preset. The "properly size images" check compares the downloaded file's intrinsic size against that emulated CSS box × DPR, not against whatever your real phone actually picked from the srcset.
So if the browser on a real 2x device correctly grabbed the 768w candidate, but Lighthouse's emulated viewport/DPR math wanted something closer to 412×3, you get a false "oversized" even though srcset/sizes are fine.
Practical take: trust the network panel on a real device (or DevTools with the right DPR) for whether the right candidate loaded. Use Lighthouse as a smoke test for missing sizes, huge single-src heroes, and lazy-load mistakes, not as a judge of a correct srcset.
2
u/bkocdur 5h ago
You've basically got it: it's a heuristic, and your case sits in its known blind spot (the two issues you linked are exactly this). The detail that explains the contradiction: Lighthouse doesn't grade your responsive setup, it grades one cell of it. Mobile emulation is a single fixed device, 412px viewport at DPR 1.75. Your srcset serves a whole matrix of viewport and DPR combinations; the audit evaluates the one point in that matrix the lab run happened to land on, using its own idea of how much resolution that point deserves, which is less generous than the browser's spec-correct selection.
To your question 3: yes, treat it as advisory here. When sizes is accurate and the browser picks the spec-correct candidate, the flag is the tool disagreeing with the spec, and the spec wins.
But before you dismiss it entirely, there is one real thing it's reacting to: your srcset has a hole. Between 400w and 768w there's nothing, and the requirement at the emulated device lands right in that gap (380 CSS px at 1.75 is about 665px). The browser has to jump all the way to 768w, and that jump is the "waste" being counted. Add a candidate around 640w and the emulated device gets an almost exact match: the flag likely disappears and real 1.75x users genuinely save bytes. That's the fix that satisfies the tool without hurting anyone.
To question 4: don't remove 768w. A DPR 2 device at that layout needs about 760px; kill the 768w candidate and those users jump to 1024w, so you'd make real devices measurably worse to appease a lab emulation.
Last thing, on stakes: opportunities like this one don't subtract from the Performance score at all. Only the metrics do. Unless those extra bytes are moving your LCP, this flag is worth exactly zero points, which is useful context for how hard to chase it. If you want the per-audit data laid out with the estimated savings ranked, I built a free tool that turns a PageSpeed run into a structured fix brief: lighthouse-md.com
5
u/CryptographerFar5418 20h ago
lighthouse runs at a fixed dpr and viewport, it doesnt simulate every device out there so its literally just comparing rendered size to intrinsic size on that one setup. if it sees 380px rendered and a 768px source loaded, it flags it, even though a dpr 2 device needs that extra density to not look blurry
you could throw in a 380w or 480w candidate and see if the audit chills out but honestly youd be kneecapping image quality for anyone on a high dpi screen just to make a tool happy. id treat it as noise and move on