Image optimization strategies
One route per technique, from unoptimized to fully optimized. Each renders the same 20-image dataset as a responsive grid; each grid item links to a large detail view (the LCP element). Run the Lighthouse harness againstnetlify serve (port 8888) to compare LCP, CLS, and bytes.
Strategies
- Naive
naivePlain <img>, full-size, no srcset/sizes/dimensions. The measurement floor. - Manual
manualHand-cut widths + srcset/sizes + baked blur over public/ files. The bash era, done right. - Auto
auto<Picture> generates formats, srcset, sizes, and width/height. Toil deleted. - Pixel-perfect
pixel-perfectsizes computed from layout tokens so the served file lands on the slot. - LQIP
lqipAuto plus a getImage() blurred placeholder and a cache-guarded fade-in. - Cropped
croppedfit=cover with per-view aspect ratios: 4:3 thumb and 16:9 cover from one imported source — two distinct build outputs. - Final
finalThe production stack: LQIP placeholder + cache-guarded fade, over pixel-perfect token widths, with an optional per-image crop.
Measured results
| Strategy | LCP (ms) | CLS | Bytes (KB) |
|---|---|---|---|
| naive | 4876 | 0.011 | 9179 |
| manual | 749↑ | 0.000 | 940 |
| auto | 1529 | 0.000 | 511 |
| pixel-perfect | 1001 | 0.000 | 231↑ |
| lqip | 1254 | 0.000 | 528 |
| cropped | 1600 | 0.000 | 546 |
| final | 1077 | 0.000 | 248 |
Cold-cache Lighthouse 13 medians (3 runs each). A warm browser reload is faster and is not a fair strategy comparison — see the README.
Key findings
- Bytes wins go to pixel-perfect and final — 231 KB and 248 KB, ~55% under
auto(511 KB) and 97% undernaive. Exactsizes+widthsderived from layout tokens means the CDN serves the slot file with no slack. - LQIP does not improve LCP — its LCP (1254 ms) is worse than
auto(1529 ms). Lighthouse records LCP when the full image is visible — after the fade-in fires — so the placeholder adds latency, not savings. LQIP's payoff is perceived speed: the user sees content at ~200 ms even though the metric clock runs longer. - manual wins LCP (749 ms) — hand-cut files served directly from
public/, no CDN transform roundtrip on/.netlify/images. - final is the production pick — matches pixel-perfect on bytes (248 KB) while LQIP delivers instant visual feedback. The 76 ms LCP delta vs pixel-perfect is the cost of the fade.