Firefox Image Lazy-loading
September 23, 2021
While contemplating what image format I should use for an image gallery (answer: webp), I stumbled upon the lazy attribute. This sounded perfect! No need to muck about with IntersectionObserver or pagination. Just toss all your images onto a page and let the browser figure the rest out.
Does it work?
I slapped few hundred images onto a page like so:
for (...) {
for (const media_id of ...) {
const img = document.createElement('img');
img.src = `img/${media_id}.webp`;
img.loading = 'lazy';
div.append(img);
}
}
Then, I opened up my devtools' network tab and loaded the page. Chrome loaded ~30 images and loaded more in as I scrolled down. Firefox loaded all of them.
Firefox config
It turns out my ESR version of Firefox (78.14.0esr) shipped with
dom.image-lazy-loading.enabled
set to false
by default.
I'd go look up what version it started shipping with a default of true
,
but by the time you read this, it's probably not going to be your problem.
After adjusting that in about:config
, I started passing
feature detection,
so I was at least doing something right now.
I reloaded my page and... it loaded all the images anyway.
Static page
Thinking this was something weird about my JS, I copied the generated DOM out of the devtools' inspector pane (those familiar with Chrome's devtools know this as "elements") and pasted it into an HTML file. Loading that page resulted in only ~10 images loading!
Random hacks
So it seems that something is wrong with my JS code.
I tried setting explicit heights on some elements.
I tried loading just 20 images at a time in a setTimeout
chain.
Nothing worked.
At this point, I started reading random bugs to see if others had run into this problem. FF bug 1542784 is the overall tracking bug for image lazy-loading and didn't turn up anything interesting. FF bug 1618240 is someone complaining that FF is too lazy, the opposite of my problem. It links to this tweet where someone's RUM shows FF loading way fewer images than Chrome.
Attribute order
FF bug 1628894 is someone complaining that
<img loading="lazy" srcset="image.png">
works but
<img srcset="image.png" loading="lazy">
doesn't. That sure is an interesting bug... I wonder what order I was using?
img.src = `img/${media_id}.webp`;
img.loading = 'lazy';
So the fix is to invert those.