Closed Bug 1618240 Opened 5 years ago Closed 2 years ago

Consider loading <img loading="lazy"> before they intersect with the viewport

Categories

(Core :: Layout, enhancement, P2)

enhancement

Tracking

()

RESOLVED WORKSFORME
Webcompat Priority P3

People

(Reporter: fvsch, Unassigned)

References

Details

(Whiteboard: [layout:backlog])

Bug 1542784 added support for <img loading="lazy"> in Gecko.

It looks like Firefox only loads lazy-loaded images when they start intersecting the viewport. As a result, when scrolling a page with lazy-loaded images the images will visibly appear "late", and if scrolling quickly they may appear after we have scrolled away. (Quick test case: https://cdpn.io/fvsch/debug/gOpmzOg/VJMxxOLWeYeM)

This is getting reported on web developer blogs as a major difference between browsers:

"Inconsistent user-experiences with native lazy-loading images"
https://www.ctrl.blog/entry/lazy-loading-viewports.html

Did you consider using a rootMargin closer to what Chrome uses, or another value between that and zero?

Changing status and issue type to clarify that it's an open question.

Are there discussions at the WHATWG or directly with Chromium folks about harmonizing this behavior to some extent?

Status: NEW → UNCONFIRMED
Type: defect → enhancement
Ever confirmed: false
Flags: needinfo?(hikezoe.birchill)
Summary: Start loading <img loading="lazy"> before they intersect with the viewport → Consider loading <img loading="lazy"> before they intersect with the viewport

IIRC, Anne commented in the PR for the lazy-load spec changes, that is the spec should mention/define the exact way. But I couldn't find it.

Anne, am I remembering correctly?

Also, I've heard that Chrome's way is too eager for lazy loading, and I received a email from a person who is interested in this inconsistency. For references here is my answer to the email.

in my opinion with any simple heuristic margin values some people would complain it's too eager/lazy.
Given that any scrollable elements can be transformed, especially scaled, also on mobile there is another concept of viewport, the visual viewport, things are complicated. I suppose a single margin value, even if it's calculated by a heuristic way, it wouldn't be sufficient for all lazy load images even in a document.

So, to me the spec should mention/define a way, but to me it looks hard.

Flags: needinfo?(hikezoe.birchill) → needinfo?(annevk)
Blocks: lazyload
Status: UNCONFIRMED → NEW
Ever confirmed: true

We should make it configurable to begin with.

So with bug 1618601 there will be various dom.image-lazy-loading.root-margin.<side> prefs. By default they're pixel values but you can also make them percentages or such with the relevant .percentage bool pref.

They need a page refresh to take effect. We should experiment with them and probably reach out to developers to help out and try to figure out what's best for everyone. We could also consider network speed / viewport size and such, too.

It doesn't define it exactly, I mainly meant that it should allow for it and it does under https://html.spec.whatwg.org/#will-lazy-load-image-steps:

If img's lazy loading attribute is in the Lazy state, img does not intersect the viewport, and img is not about to intersect the viewport, then return true.

Note: This allows for fetching the image during scrolling, when it does not, but is about to intersect the viewport.

Dominic might be able to comment on specifics for Chrome, but I would expect these heuristics to at least change a bit over time as we learn more about ideal behavior. (As Emilio is also saying above.)

Flags: needinfo?(annevk) → needinfo?(domfarolino)

Yeah, as of right now Chrome's implementation is pretty aggressive (lazy loading isn't very "lazy"), but my understanding is that we're running some experiments right now with modified values to try and optimize our approach. Emilio: would it be useful to introduce you to some people running the experiments so you all might be able to sync up on what's been learned?

Flags: needinfo?(domfarolino)

Yeah, sure, that'd be useful!

The strong difference between Chrome and Firefox is coming up in people's RUM metrics:
https://twitter.com/TimVereecke/status/1248628242661007360

As smfr noted in the Twitter thread, there is an ongoing discussion. https://github.com/whatwg/html/issues/5408

Lazy loading should not forget the user experience. I develop an image website, and scrolling down with loading="lazy" in Firefox is very unsatisfying because the images are never ready when they enter the viewport, even if I scroll slowly! Chrome does it much better in this regard.

Whiteboard: [layout:backlog]

I am also thinking that Firefox should be more eager to load images, at least the ones in the next viewport. It could also use additional heuristics, notably the fact that an image has an intrinsic size. Without it, the layout will be jumpy, so it would be better to be more eager to download these images in advance.

Scrolling with the mousewheel I can see the image load a little bit which is mildly annoying. Scrolling with page up/page down however shows entire image loading and make the experience very unpleasant.

Could it be good to have img load within one page up/down of the current viewport?

Moving to Layout since any of the work we do on this will happen there.

Setting to P2 per our backlog prioritization guidance: https://wiki.mozilla.org/Platform/Layout#Backlog_Tracking_in_Bugzilla

Component: DOM: Core & HTML → Layout
Priority: -- → P2

The current implementation of Firefox's lazy load makes Firefox appear to be a slow browser. I don't think there's a solution to this issue as there are so many variables. The viewers internet speed, how fast they scroll, the number of images on the page, how large the images are, all these variables make finding a solution that works for all impossible.

The best solution is to have a switch in Preferences for lazy load, I know I would disable this feature, but the vast majority of users would still see Firefox as slow unless this preference is set as disabled by default.

The spec now has suggestions for this, added in https://github.com/whatwg/html/pull/5917

See https://github.com/whatwg/html/issues/5408#issuecomment-643505639 for what Chromium is currently doing. The relevant distances are in https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/core/frame/settings.json5 (e.g. "lazyImageLoadingDistanceThresholdPx4G").

Webcompat Priority: --- → P3
Depends on: 1703048
Depends on: 1713811
Depends on: 1722574
Depends on: 1742203

If users try to click, but the page jumps under them due to lazy loading, they may hit the wrong spot. Possibly even end up on Twitter or Google Maps and get sick as a result. Using about:config to disable lazy loading does not yet prevent this, either.

Depends on: 1750034

Disabling lazy load in about:config works fine.

dom.image-lazy-loading.enabled -> default is true set to false

We've been doing this for a while

Status: NEW → RESOLVED
Closed: 2 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.