whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
8.12k stars 2.67k forks source link

Lazy loaded images and iframes should be forced to eager when printing #6581

Open grakz opened 3 years ago

grakz commented 3 years ago

Issue summary

When printing a page that contains lazy loaded images or iframes that have not been shown on screen yet these are not loaded but shown as empty elements.

Currently the lazy loading attributes spec and the actual user agent implementations do not consider printing, however for many website owners who's users depend on printing (either on paper or to PDF), this issue is a hurdle that prevents them from moving to native lazy loading.

Expected behavior

Since lazy loading should be transparent to the user, the user agent should load all images and iframes immediately prior to showing a print preview.

Possible solutions

There are two potential solutions, the first seems most natural to me, though the second will also benefit other uses of the Intersection Observer.

  1. The user agent should treat each img and iframe element as having the lazy loading attribute set to eager when the media type is equal to print.
  2. For each target, of each observing IntersectionObserver, set isIntersecting to true when the media type is equal to print.

Potential issues

  1. Confusing to user why print preview/dialog is not being shown to users on slow connections or on pages with a large number of lazy loaded elements.

Implementation bugs

Related Links

annevk commented 3 years ago

@domfarolino @emilio it seems like this is a blocker for Wikipedia and perhaps also others.

grakz commented 3 years ago

I added a test page, that should show the numbers 1 through 6 when printing.

Printing this page fails in Chrome and Safari and succeeds in Firefox and Safari.

EDIT: It turns out I forgot to enable lazy loading in Safari, with lazy loading enabled Safari also fails.

Firefox 74, Windows 10

image

Chrome 92, Windows 10 / Chrome 89 Android 10

image image

Safari, macOS 11.2.3 / iOS 14.4.2

image image

emilio commented 3 years ago

I fixed this ages ago in https://bugzilla.mozilla.org/show_bug.cgi?id=1648064.

emilio commented 3 years ago

It's not clear to me that the spec needs special-casing this? You could argue that the print document always gets displayed "fully" and thus all images should be loaded.

annevk commented 3 years ago

Yeah, I think in terms of normative requirements we are okay, but it might be worth calling out in a note as a thing to pay attention to. (Also great that we already do this and it seems to be mostly a Chrome bug.)

grakz commented 3 years ago

I am an idiot. I forgot to turn on lazy loading in Safari (it's not enabled by default yet). When you enable it, Safari also fails to print the page correctly.

It seems only Firefox is handling this case correctly. Though I noticed that on a slow connection the Firefox print dialog continues to update in the background without notifying the user that the content is still being loaded (Firefox 89.0a1).

Krinkle commented 3 years ago

This may be obvious, but I wonder how browsers should (or do) behave when a user initiates the print workflow before the load event was reached (or some other significant event, like document readyState complete). That is perhaps less common, but it might be useful to think about. This feels like logically the same kind of scenario from the user's perspective, where (below-the-fold) HTML chunks and style/image subresources can also still be pending, and this situation can arise even without lazy-loading.

If vendors agree that users expect printing to render the full document (vs only the HTML and images so far in their viewport or buffer), then that would (or perhaps already does) get subjected to the same treatment. Whether we go for real-time updates, or telling the user we're waiting, or asking them after a certain threshold, etc. The "wait" would track the load event, plus another such wait-for sequeunce for any new subresources initiated around the time we switched to eager loading.

(Feel free to ignore if this is obvious or not helpful. I didn't see this mentioned and figured it might help to look at it from this prespective as well.)

grakz commented 3 years ago

@Krinkle I agree with your thinking. For the user it should be the same. Currently Chrome, Firefox and Safari all show different behaviors when users try to print a document before it finishes loading:

So there is no agreement on between the vendors, but how should browsers behave when a user initiates the print workflow before the load event was reached?

emilio commented 3 years ago

In Firefox this depends on whether it's window.print() or user print what gets called. For window.print(), we do wait until the load event and other browsers do the same, but otherwise we do print a potentially incomplete page.

grakz commented 3 years ago

@emilio I loaded an html page with a single 30mb image in Firefox 89 in an artificially squeezed internet connection (setting my ethernet to 10mbit half-duplex). I selected print in the print menu. The print preview opens and it then silently updates after the image finishes loading. See the attached video for what happens.

https://user-images.githubusercontent.com/21514469/114849618-37d6ef00-9de0-11eb-9559-6b4187943592.mp4

emilio commented 3 years ago

Ah, I see what you mean, that's an slightly different case than what I was thinking of.

I meant that if you Ctrl+P before the load event fires we'll just take the dom as it is (you can see this if you try to print the html spec mid load for example). If you window.print() however, we'll wait for the load event to fire before showing the print dialog. This is a compat requirement I think, and matches other browsers. If in your example you insert a window.print() you should see that happening.

However even with the print menu / Ctrl+P, we do wait for resources to load (such as images, like I'm your example). This is needed to make <source media=print>, lazy loaded images, images loaded from media queries only in print media, etc work as expected.

zcorpan commented 2 years ago

https://bugs.chromium.org/p/chromium/issues/detail?id=875403 is now fixed by @chrishtr, with the following caveats:

This works for user-initiated print, but not scripted print.

I'm currently thinking it isn't worth it to implement for iframes, because they are much more complicated and/or slow to load than images, and I'm not so sure there is enough value. Please comment if you think there is, and if so why.

domfarolino commented 2 years ago

I meant that if you Ctrl+P before the load event fires we'll just take the dom as it is

This seems to be at odds with:

However even with the print menu / Ctrl+P, we do wait for resources to load

I just want to be clear in my understanding that Firefox does allow you to print a document with incomplete resources. That is, the print dialog won't explicitly "wait" for pending resources to load before allowing a print (via CTRL+P). Though if the resources do happen to load while the print preview is displayed, it gets updated to show this. But if I'm misunderstanding please correct me.


Regarding:

Yeah, I think in terms of normative requirements we are okay, but it might be worth calling out in a note as a thing to pay attention to. (Also great that we already do this and it seems to be mostly a Chrome bug.)

Do we think there is any remaining action to be taken here in the spec? It looks like Chrome now, for user-initiated prints, makes all lazyload resources load immediately and block the load event. We set a 2 second timer to wait for these resources, and which ever comes first (load event, or 2 seconds is up) we then show the print dialog. Perhaps we require such logic in the spec?

chrishtr commented 2 years ago

Update: Chromium now forces eager when printing via user-initiated and script print, as well as with iframes.

emilio commented 2 years ago

I meant that if you Ctrl+P before the load event fires we'll just take the dom as it is

This seems to be at odds with:

However even with the print menu / Ctrl+P, we do wait for resources to load

I just want to be clear in my understanding that Firefox does allow you to print a document with incomplete resources. That is, the print dialog won't explicitly "wait" for pending resources to load before allowing a print (via CTRL+P). Though if the resources do happen to load while the print preview is displayed, it gets updated to show this. But if I'm misunderstanding please correct me.

This is not right. Sorry, I should've realized that my previous comment wasn't super-clear if you don't know about how Firefox does printing.

Let me try to clarify and let me know if there's something still unclear.

In order to print in Firefox, there are actually two documents involved, not one:

This is for a variety of reasons (main one being that you can keep displaying the website while you're printing, though there are other historical ones).

The details are a bit fuzzy in my mind (I could page this back completely if required), but there are some things that are cloned as-is from the original document into the clone document (like style sheets), and others (mostly the ones that can be triggered via media queries or so, like images) where the clone document does trigger its own resource load.

The two sentences you quoted are about different documents:

Does that explain the Firefox setup a bit better?

tgrushka commented 1 month ago

This lazy-loading decision also negatively impacts accessibility and accessibility testing. Who makes these decisions, and why are they made without consultation with accessibility SMEs?