HTML-only conditional lazy loading (via preload + media)
The accepted practice is to not add lazy-loading to images above the fold, especially the LCP image, since doing so can delay their loading until the browser has determined they are definitely in the viewport. One problem though is that "above the fold" depends on screen size: an image can be above the fold on desktop and below it on mobile. With native lazy loading and static HTML (e.g., without device detection on the server side or JavaScript), you normally have to pick one behavior and get it wrong for part of your users.
But there's a small workaround that seems to work. Browsers won't delay the loading of an image if it's already been fetched. You can take advantage of that by conditionally preloading the image using a media query, then marking the image as lazy later. I tested it using the HTTP link header, but may also work fine with a <link rel="preload"> tag.
Conceptually:
Link: </hero.jpg>; rel=preload; as=image; media="(min-width: 1024px)"
<img src="/hero.jpg" loading="lazy" />
Effect:
Desktop: preload fires → image loads eagerly (good for LCP)
Mobile: preload ignored → image lazy-loads
I'm using this in book pages and sidebar images at https://pccd.dites.cat. Example: https://pccd.dites.cat/obra/Conca-Guia_(1996)%3A_Els_primers_reculls_de_proverbis_catalans
In that layout, the cover image is above the fold on desktop but not on smaller devices — so it's eagerly loaded where Lighthouse recommends it, and lazy-loaded where it makes sense.
Caveats:
- Not documented or discussed anywhere (but seems to work fine in major browsers)
- Requires preloading, which may not always be practical (or intended)
But this gives you HTML-only, viewport-dependent lazy loading.