FE Lead prep · ref 06
srcset/sizes) · 3. Right loading (lazy below / prioritize LCP) · 4. Reserve space (width/height).<picture> = format fallback; browser takes first supported <source type>, <img> = floor.<picture>
<source type="image/avif" srcset="h.avif">
<source type="image/webp" srcset="h.webp">
<img src="h.jpg" width=800 height=600 alt>
</picture>
srcset w-descriptors = menu: file + its real px width (800w=800px wide). Same image, many sizes.sizes = rendered slot width so browser picks before layout (preload scanner needs it).sizes) × DPR → smallest file ≥ that. (33vw slot on a big laptop → tiny file; small phone @ DPR3 → big file.)<picture media> = art direction = browser uses first matching media = different crop per breakpoint.srcset works on BOTH <img> and <source>. Plain <img srcset sizes> is enough for resolution — only use <picture> for format (source type) or crop (source media).srcset/sizes/type/media → on <source>; alt/width/height/loading/fetchpriority/decoding → only on <img> (the required fallback). Browser uses first <source> matching type+media.Accept header → format axis gone, back to plain <img>.<img srcset="h-400 400w, h-800 800w,
h-1600 1600w"
sizes="(max-width:600px) 100vw, 33vw"
width=800 height=600 alt>
| Image | Do | Why |
|---|---|---|
| Below fold | loading="lazy" + decoding="async" | save bytes, free network |
| LCP (hero/1st) | fetchpriority="high", never lazy (opt. preload) | it's the metric — Google test cut LCP 2.6→1.9s |
Save-Data: on header → CDN returns lighter image, same URL. No JS, explicit intent → preferred. Must Vary: Save-Data (cache).navigator.connection: saveData, effectiveType (slow-2g…4g), downlink, rtt → smaller srcset / skip hero video. Chromium-only + estimate → enhancement, not a gate.@media (prefers-reduced-data) → skip CSS bg images (decorative). Limited support.react-adaptive-hooks (useSaveData/useNetworkStatus).width+height → browser derives aspect-ratio, reserves space before load.aspect-ratio; responsive → img{height:auto} + attrs.<Image> (next/image) → srcset, lazy, dims, blur baked in → correct by default.<img> so it can't regress across teams.fetchpriority=high and is never lazy — a blanket lazy rule catching the hero is the most common own-goal.”width/height so the box is reserved before the bytes land — that's most of CLS gone.”<Image> component + a CI image budget — not hand-authored <picture>.”Save-Data users at the CDN — explicit intent, works everywhere. navigator.connection is Chromium-only and a guess, so it's enhancement, never a gate; and I Vary: Save-Data.”Sources: MDN — fix image LCP · web.dev — fetchpriority · web.dev — responsive images · web.dev — image CDNs · HTTP Archive — Media
fetchpriority=high above, lazy below.sizes wastes everything — must match real rendered width or browser picks too-big a file.srcset = resolution switching (same image); different crop needs <picture media> (art direction). Don't reach for <picture> when a plain <img srcset> suffices — only for format or crop.width/height — dimensionless images shoving content = #1 image CLS.<Image> component + CI budget.Save-Data header at CDN (explicit, works everywhere; Vary: Save-Data). navigator.connection is Chromium-only + a guess → enhancement, never the gate.