Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazyload images and iframes #3752

Open
wants to merge 20 commits into
base: master
from

Conversation

@bengreenstein
Copy link

commented Jun 8, 2018

@domenic

This is a draft of spec changes to support a lazyload attribute in iframe and img elements.


Issue: #2806
Tests: https://chromium-review.googlesource.com/c/chromium/src/+/1417117 (wpt export)


/embedded-content.html ( diff )
/iframe-embed-object.html ( diff )
/images.html ( diff )
/index.html ( diff )
/indices.html ( diff )
/infrastructure.html ( diff )
/urls-and-fetching.html ( diff )

@domenic

This comment has been minimized.

Copy link
Member

commented Jun 12, 2018

I did another minor pass; PTAL.

@domenic
Copy link
Member

left a comment

Some issues with the metadata fetcher

Show resolved Hide resolved source Outdated
Show resolved Hide resolved source Outdated
source Outdated
<li><p>&#x231B; Set <var>request</var>'s <span
data-x-href="https://fetch.spec.whatwg.org/#concept-request-add-range-header">range header
</span> to request as much data from the beginning of the image file as the user agent
determines is reasonable to retrieve metatdata.</p></li>

This comment has been minimized.

Copy link
@domenic

domenic Jun 27, 2018

Member

You'll want to explicitly refer to and use https://fetch.spec.whatwg.org/#concept-request-add-range-header here

This comment has been minimized.

Copy link
@bengreenstein

bengreenstein Jun 28, 2018

Author

I do. What am I missing?

This comment has been minimized.

Copy link
@domenic

domenic Jun 28, 2018

Member

The issue is that you're not actually using the operation defined there. You're linking the text "range header" to it, but that's not how you call functions when writing software.

You need to actually invoke it, by using the right phrase ("add a range header") and passing it the right arguments (in this case, I believe, request, 0, and a user-agent-chosen value).

@domenic
Copy link
Member

left a comment

Metadata fetching looks good to me editorially now. Eager to hear others thoughts on whether it provides the right foundation for interoperability.

Things were fixed

@annevk
Copy link
Member

left a comment

You also need to update the element indexes to include this attribute for img and iframe.

Should this influence https://fetch.spec.whatwg.org/#concept-request-priority somehow?

Show resolved Hide resolved source Outdated
source Outdated
policy</span> to the current state of the element's <code
data-x="attr-img-referrerpolicy">referrerpolicy</code> attribute.</p></li>

<li><p>Then <span data-x="concept-request-add-range-header">add a range header</span> to

This comment has been minimized.

Copy link
@annevk

annevk Jul 25, 2018

Member

@jakearchibald could you please review this?

source Outdated
elements</span>. If the element's <code data-x="attr-iframe-lazyload">lazyload</code> attribute
is in the <span data-x="attr-lazyload-on-state">On</span> or <span
data-x="attr-lazyload-auto-state">Auto</span> states, and the element's CSS layout box does not
intersect the <span>viewport</span>, then running these steps may be deferred until such

This comment has been minimized.

Copy link
@annevk

annevk Jul 25, 2018

Member

I don't think this works for about:blank and such, does it? What does this map to in say Blink's C++?

This comment has been minimized.

Copy link
@scott-little

scott-little Dec 14, 2018

Since the wording already says "running these steps may be deferred" instead of "must", I don't think we really need to call out the trivial cases here, right?

This comment has been minimized.

Copy link
@domenic

domenic Dec 18, 2018

Member

Agreed, the "may" seems fine? Unless there are cases in Blink's implementation that are never lazy loaded, which maybe everyone should agree on?

@jakearchibald jakearchibald self-requested a review Jul 25, 2018

@jakearchibald
Copy link
Collaborator

left a comment

Also: img.decode() waits for the image fetch to complete. With lazyload, this may take a long time, or might never happen. Is that the intent? Feels like decode() is a strong signal that the developer wants the image to fetch.

source Outdated
user agent determines is reasonable to retrieve metatdata.</p></li>

<li><p><span data-x="concept-fetch">Fetch</span> <var>request</var>, and use the metadata
contained in the response as appropriate for the image.</p></li>

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Jul 25, 2018

Collaborator

I'm not sure how much hand-waving is ok here, but this seems pretty hand-wavey.

We plan to use the metadata to lay out the image, right? Is that worth documenting as a possible consequence?

What happens if the response is a 404 or 500? Feels like we could call the image a failure at that point. We should probably do that for all not-ok responses, unless it looks like a consequence of making the range request (416).

What happens if the response is a 200? We'd download the whole image, would we download it again? Perhaps we'd add it to the image memory cache in that case? Or maybe terminate the fetch after fetching the metadata bytes?

What happens if the response is a 206, but we fail to parse the start? Again, we could call the image a failure, and not bother fetching any more.

What happens if the response is a 206, but the range starts at a point other than 0. It's pretty important to reject the response in this case, as reading it as if it were the start of the resource could leak data.

What happens if the response is a 206, starts at 0, but returns fewer bytes than requested?

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Jul 25, 2018

Collaborator

What happens if, during the metadata fetch, the main fetch begins? What happens if the metadata fetch arrives later than the main fetch?

From earlier discussion around this feature, I think the intention is to throw away anything learned from this metadata once the main fetch happens. Eg, if the partial fetch tells us the size is 100x100, but the main fetch tells us it's 500x500, the image will be laid out at 500x500. This means we aren't merging the results of two responses, and that's pretty important for security & interoperability. It should probably be spelled out here.

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Jul 25, 2018

Collaborator

In terms of validating the partial response, here's what I'm playing with in background fetch https://wicg.github.io/background-fetch/#validate-partial-response-algorithm.

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Jul 25, 2018

Collaborator

I just remembered that we still load image data from a 404 etc, so ignore that part.

This comment has been minimized.

Copy link
@bengreenstein

bengreenstein Dec 14, 2018

Author

If the response is a 200 and we get the full image, or if the full image is contained in the 206, we use it and don't fetch it again. I'm not sure how much we want to codify this logic into the spec.

We should reject a range that doesn't start at 0. We best effort decode one that does, even if it is shorter than the requested range as this a common case with tiny images. If we can see that the image is larger than the amount returned and the amount returned is less than the range requested, we still try to decode best effort. Again I'm not sure how much of this we want to include in the spec.

If the main fetch begins during the metadata fetch, we cancel the metadata fetch.

The main fetch should override the metadata fetch, but of course the network stack may use data cached from the metadata fetch to reduce the size of the main fetch.

This comment has been minimized.

Copy link
@domenic

domenic Dec 18, 2018

Member

We plan to use the metadata to lay out the image, right? Is that worth documenting as a possible consequence?

I think documenting this is a good idea, especially because then we can require that the metadata be ignored if later the main fetch comes back with a different result.

If the main fetch begins during the metadata fetch, we cancel the metadata fetch.

This needs to be in the spec, perhaps as something like "The user agent may cancel this fetch if the 'update the image data' algorithm begins its own independent fetch".

but of course the network stack may use data cached from the metadata fetch to reduce the size of the main fetch.

So like, do a range request including the rest of the bytes? Eek, that's tricky, and would requiring modifying the main image data fetch algorithm.

source Outdated
<p>If the <code>img</code> element's <code data-x="attr-img-lazyload">lazyload</code> attribute is
not in the <span data-x="attr-lazyload-off-state">Off</span> state, the user agent may immediately
fetch metadata from the image header. To fetch image metadata, the user agent must run the
following steps:</p>

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Jul 25, 2018

Collaborator

Should we be explicit that this mustn't happen if the primary fetch for the resource has begun?

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Jul 25, 2018

Collaborator

It probably shouldn't happen if the image is in the list of available images. It's a waste otherwise.

Is there any benefit to checking if the image is in the HTTP cache at this point?

This comment has been minimized.

Copy link
@domenic

domenic Dec 18, 2018

Member

+1 to aborting if the image is in the list of available images.

Not sure I see the idea about the HTTP cache.

source Outdated
<tr>
<td><dfn><code data-x="attr-lazyload-auto">auto</code></dfn>
<td><dfn data-x="attr-lazyload-auto-state">Auto</dfn>
<td>Indicates that the user agent may determine the fetching strategy (the default).

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Jul 25, 2018

Collaborator

I think there are cases where we need to define 'auto'. Expectations are pretty strong when it comes to new Image(). Perhaps "off" is the default unless the image was created by the regular document parser (not innerHTML and createContextualFragment).

This comment has been minimized.

Copy link
@domenic

domenic Dec 18, 2018

Member

I'm in favor of leaving auto free to experiment for now...

This comment has been minimized.

Copy link
@zcorpan

zcorpan Mar 6, 2019

Member

new Audio() sets preload=auto, maybe new Image() could set load=eager to match expectations.

source Outdated

<p>A <dfn>lazy loading attribute</dfn> is an <span>enumerated attribute</span>. The following
table lists the keywords and states for the attribute &mdash; the keywords in the left column map
to the states in the cell in the second column on the same row as the keyword.</p>

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Jul 25, 2018

Collaborator

What happens if this value is changed after element creation? Eg, if I switch from "on" to "off". Feels like the image should immediately load. Worth spelling out?

This comment has been minimized.

Copy link
@domenic

domenic Dec 18, 2018

Member

This is explicit in the spec's

user agents must obtain images immediately when the CSS boxes those images intersect the viewport, or when the corresponding img element's lazyload attribute is in the Off state

But maybe we can add a clarifying note right after that paragraph, saying "This means that if the author changes the lazyload attribute's value to Off, and the image has not already been obtained, it will immediately be obtained."

This comment has been minimized.

Copy link
@zcorpan

zcorpan Mar 6, 2019

Member

This seems like a possibly common use case. Is it clear that changing the state is the way to load the image, or should there be a load() method (like for media elements)?

This comment has been minimized.

Copy link
@zcorpan

zcorpan Mar 6, 2019

Member

I just realized that load() would conflict with load IDL attribute...

@Malvoz Malvoz referenced this pull request Aug 8, 2018

Open

Demo has issues #79

aarongable pushed a commit to chromium/chromium that referenced this pull request Aug 16, 2018

LazyLoad: Implement support for "lazyload" attribute on frames.
This CL implements support for the "lazyload" attribute on frames,
according to whatwg/html#3752, and as part of
the LazyLoad feature. The accepted values are:

"on", which causes the browser to lazily load a frame even if it's
same-origin or nested inside another lazyloaded frame,

"off", which causes the browser to avoid lazily loading this frame or
any of it's children (unless those children are marked with
lazyload="on"),

"auto", which activates the default behavior, and is therefore not
explicitly handled in code.

Bug: 873358
Change-Id: I2fde65adb15216260291b08e39888a2363f44d4a
Reviewed-on: https://chromium-review.googlesource.com/1176293
Commit-Queue: Scott Little <sclittle@chromium.org>
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583841}

aarongable pushed a commit to chromium/chromium that referenced this pull request Sep 19, 2018

rajendrant Commit Bot
LazyLoad: Implement support for "lazyload" attribute on images
This CL implements support for the "lazyload" attribute on images,
according to whatwg/html#3752, and as part of
the LazyLoad feature. The accepted values are:

"off", which causes the browser to avoid lazily loading the <img> element

"on" and "auto", activate the default behavior of lazily load the <img> element

When the attribute is changed to "off", the deferred image loads immediately.

Bug: 875080
Change-Id: I839926a9827d019f23aafc40f8315476fe1b3048
Reviewed-on: https://chromium-review.googlesource.com/1197782
Reviewed-by: Hiroshige Hayashizaki <hiroshige@chromium.org>
Reviewed-by: Takashi Toyoshima <toyoshim@chromium.org>
Commit-Queue: rajendrant <rajendrant@chromium.org>
Cr-Commit-Position: refs/heads/master@{#592599}

@Malvoz Malvoz referenced this pull request Sep 25, 2018

Open

'importance' + 'loading' attributes #699

0 of 2 tasks complete
@sideshowbarker
Copy link
Member

left a comment

I’d suggest that since the change to the CONTRIBUTING.md and README.md files arenn’t directly related to the substance of the rest of this patch (lazyload feature), it’d be preferable for the CONTRIBUTING.md and README.md changes to be in separate patches from this patch. It’d be fine if they are just a separate commits as part of PR #3752 but not sure if that would happen, given that the policy here for PRs is that they result in a single (squashed) commit that gets merged to master

@sideshowbarker
Copy link
Member

left a comment

The changes to dev/style.css for adding the syntax-highlighter styles have already been merged into master, so they should be dropped from this patch.

@sideshowbarker
Copy link
Member

left a comment

OK, I’m now realizing that this reason some unrelated changes are showing up in the diff here are that this patch includes some merges? So it seems like it needs to be rebased against master to clear those away?

@bengreenstein bengreenstein force-pushed the bengreenstein:lazyloading branch from d2af159 to da6a6f8 Oct 2, 2018

@annevk

This comment has been minimized.

Copy link
Member

commented Dec 11, 2018

@bengreenstein could you rebase this against master and then force push the resulting changeset to get rid of the merge commits? As it stands it looks like this is proposing a number of changes against dev/styles.css for instance, which doesn't seem correct.

Ben Greenstein and others added some commits May 31, 2018

Various nits and cleanups:
- Remove "lazyload hint" concept and refer instead to states of the attribute directly
- IDL attribute casing should be lazyLoad, not lazyload
- Be a bit more precise in the iframe processing model
- Remove domintro for reflecting attributes (both this one and the one added for img.decoding, erroneously)
@sideshowbarker

This comment has been minimized.

Copy link
Member

commented Dec 14, 2018

This branch is now in a state that it can’t be rebased against master without multiple merge conflicts.

@bengreenstein bengreenstein force-pushed the bengreenstein:lazyloading branch from b2cdf21 to c093e8c Dec 14, 2018

@annevk

This comment has been minimized.

Copy link
Member

commented Apr 8, 2019

Was it discussed whether or not this should impact the "delays the load event" concept? I could not find it skimming through the above.

@bzbarsky bzbarsky referenced this pull request Apr 8, 2019

Open

Lazy loading #151

@felixarntz felixarntz referenced this pull request Apr 9, 2019

Open

Update lazyload to meet current best-practice #414

0 of 6 tasks complete
@bcardarella

This comment has been minimized.

Copy link

commented Apr 10, 2019

Has there been discussion anywhere about the use of skeleton images for the perceived user experience? A baked in image loader like this would be very helpful but if we are talking about slower connections the experience for the user will be greatly diminished if when they bring the unloaded image into the viewport there is nothing for a few seconds.

@yoavweiss

This comment has been minimized.

Copy link
Collaborator

commented Apr 11, 2019

Was it discussed whether or not this should impact the "delays the load event" concept? I could not find it skimming through the above.

My understanding is that since the lazy loaded images are not kicking off the "update the image data" algorithm, they are not supposed to delay the load event. Should we add a note calling that out more explicitly? Or is there something normative missing on that front?

@annevk

This comment has been minimized.

Copy link
Member

commented Apr 12, 2019

Looking through this some more I have some more feedback:

  • Doing a range request without requiring CORS seems problematic as it'll complicate whatwg/fetch#721 quite a bit. There's also a lot of duplication in building up that request that I'd prefer to see deduplicated. It might also be good if @jakearchibald does another review round.
    • I don't understand what primitive "Responses that begin after byte 0 must be ignored." builds on.
  • I don't understand how "update the image data" is not kicked off. The relevant mutations are not conditional upon this new feature. (I mean, I guess it is a bit, but it seems optional and not super clear.)
  • Say that was fixed and it was clearly conditional. What if the conditions were met before the load event fired? I'd think it still shouldn't delay the load event, right?

<li><p><span data-x="concept-request-add-range-header">Add a range header</span> to
<var>request</var> starting at byte 0 and ending with as many bytes of the image file as the
user agent determines is reasonable to retrieve metatdata.</p></li>

This comment has been minimized.

Copy link
@JoshTumath

JoshTumath Apr 13, 2019

Typo 🙂

Suggested change
user agent determines is reasonable to retrieve metatdata.</p></li>
user agent determines is reasonable to retrieve metadata.</p></li>
<p>If the <code>img</code> element's <code data-x="attr-img-loading">loading</code> attribute is
not in the <span data-x="attr-loading-eager-state">Eager</span> state, the user agent may
immediately <dfn>fetch image metadata</dfn> for an <code>img</code> element <var>el</var> by
running the following steps:</p>

This comment has been minimized.

Copy link
@JoshTumath

JoshTumath Apr 13, 2019

To save needing to fetch image metadata, could we first check if the width and height attributes are specified and assume the image dimensions from that?

This comment has been minimized.

Copy link
@mikesherov

mikesherov Apr 13, 2019

The usage of may here only intends to allow retrieval of this metadata and not explicitly forbid it. There are proposals like https://github.com/WICG/intrinsicsize-attribute and h specifier for srcset that also attempt to address the issue, so I think the intent here is to solve the lazyload problem separate from the “discover the intrinsic size of an image” problem.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

commented Apr 17, 2019

@annevk

I don't understand what primitive "Responses that begin after byte 0 must be ignored." builds on.

Yeah, I agree that's pretty hand-wavy. Here's how I did it in background fetch https://wicg.github.io/background-fetch/#extract-content-range-values-algorithm. Happy for that to be moved into fetch if it's something multiple specs need to do.

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

commented Apr 17, 2019

Is it intentional that the DOM attribute is loading, but the IDL is still lazyLoad?


<li>
<p><span data-x="concept-fetch">Fetch</span> <var>request</var>, and use the metadata
contained in the response as appropriate to lay out the image. The user agent may cancel this

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Apr 17, 2019

Collaborator

What if this data arrives later than the full image, and the two results have different dimensions? It feels like the ordering here needs to be a 'must' not a 'may'.

This comment has been minimized.

Copy link
@othermaciej

othermaciej Apr 17, 2019

I think the important must should be that the user agent must ignore the results of this load if the actual image load has already determined a size. It's probably more good than bad if the image load has started but not gotten enough data to determine a size; and it doesn't matter if the load has already finished but has not been processed yet for some reason, if the UA has already determined the size the real way, the result should be ignored.

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Apr 25, 2019

Collaborator

I agree this is the most sensible thing to do. Just needs to be in the spec.

@@ -118961,6 +119105,14 @@ interface <dfn>External</dfn> {
<td> "<code data-x="attr-img-decoding-sync">sync</code>";
"<code data-x="attr-img-decoding-async">async</code>";
"<code data-x="attr-img-decoding-auto">auto</code>"
<tr>
<th> <code data-x="">load</code>

This comment has been minimized.

Copy link
@jakearchibald

jakearchibald Apr 17, 2019

Collaborator

Needs updating?

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

commented Apr 17, 2019

In general, I'm still worried about the vagueness of the auto behaviour.

const img = new Image();
img.src = url;
img.onload = () => {
  // ready!
};

Or more recently:

const img = new Image();
img.src = url;
await img.decode();
// ready!

…are common ways to preload images. It's also likely that developers will wait for these to load before activating particular behaviours (especially if the images are going to be used in a canvas).

Unless I'm misreading, this spec change means onload or onerror may never fire, and img.decode() may never resolve.

It feels like when img.decode is called, the image must be fetched. But I'm less sure what to do about the first example. Thoughts:

When src is set, queue a (micro)task. If the image is not connected to a document, load the image eagerly. (I'm not sure this will solve all preloading cases)

Or, if the img was not parser-inserted, and loading is auto, it must eagerly load.

Or, load eagerly if a 'load' listener is added (urgh).

@PickJBennett

This comment has been minimized.

Copy link

commented Apr 17, 2019

Serious question. Why limit lazy loading to <img> and <iframe> tags? Why not allow it to be set on all elements that request an asset. Examples might be <picture>, <video>, <audio>, <source> for the two before, and <object> or <embed> tags.

Maybe the exception being <link> tags, unless by doing so would allow asynchronous stylesheet loading?

@zcorpan

This comment has been minimized.

Copy link
Member

commented Apr 17, 2019

picture is already covered since it's the img that is doing the loading.

I would expect video and audio to support this eventually (hence why it was renamed from load to loading; media elements already have a member called load), but it needs to be well-defined how it affects the loading algorithm.

object and embed are typically treated as legacy at this point and don't get new features that are added to e.g. iframe or img.

@smfr

This comment has been minimized.

Copy link

commented Apr 17, 2019

WebKit bug: https://webkit.org/b/196698

@othermaciej

This comment has been minimized.

Copy link

commented Apr 17, 2019

In general, I'm still worried about the vagueness of the auto behaviour.

When src is set, queue a (micro)task. If the image is not connected to a document, load the image eagerly. (I'm not sure this will solve all preloading cases)

Sounds right to me (unless the author explicitly adds "loading=lazy" to their out-of-document image).

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

commented Apr 17, 2019

What's the expected behaviour if:

  1. An lazy image fully loads within the viewport.
  2. The image is scrolled out of view.
  3. The src of the image is changed.

Right now, then src changes I think we keep rendering the old image until (at least) the metadata for the new image arrives.

In the above case would we still send a range request? Once we have this data I assume we should ditch the old image data and render transparent? Should we spec that?

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

commented Apr 17, 2019

When src is set, queue a (micro)task. If the image is not connected to a document, load the image eagerly. (I'm not sure this will solve all preloading cases)

Sounds right to me (unless the author explicitly adds "loading=lazy" to their out-of-document image).

It's worth a try I guess. Although this would break:

const div = document.createElement('div');
div.style.display = 'none';
document.body.append(div);

const img = new Image();
img.src = url;
div.append(img);

img.onload = () => {
  div.style.display = 'block';
};

I don't know how popular this pattern is in the wild.

@mikesherov

This comment has been minimized.

Copy link

commented Apr 17, 2019

Once we have this data I assume we should ditch the old image data and render transparent? Should we spec that?

Wouldn’t this be different behavior then from how <picture> works, which I think still displays the old image until the new image is decoded?

@jakearchibald

This comment has been minimized.

Copy link
Collaborator

commented Apr 18, 2019

Ohh, so it only switches once the new image has been fully loaded? It won't show half or it, or any of the progressive passes?

@mikesherov

This comment has been minimized.

Copy link

commented Apr 18, 2019

IANASA (I am not a spec author :-)), but I believe the relevant section is described here under the section :

User agents are encouraged to run this algorithm in particular when the user changes the viewport’s size (e.g., by resizing the window or changing the page zoom), and when an img element is inserted into a document, so that the density-corrected intrinsic width and height match the new viewport, and so that the correct image is chosen when art direction is involved.

http://w3c.github.io/html/semantics-embedded-content.html#the-picture-element

@zcorpan

This comment has been minimized.

Copy link
Member

commented Apr 18, 2019

That is when to run the "environment changed" algorithm, not about when to update presentation to the new image. When to update is step 15 (which is after the new image has been completely fetched, and decoded enough to determine that it's not completely corrupted; possibly implementations decode fully).

When changing src, the relevant part is

Furthermore, the last task that is queued by the networking task source once the resource has been fetched must additionally run these steps:

https://html.spec.whatwg.org/multipage/images.html#updating-the-image-data

@r00dY

This comment has been minimized.

Copy link

commented May 7, 2019

Hey guys,

Have anyone considered how does loading="lazy" affect responsive images and srcset and sizes attributes?

When user agent parses HTML, it has no idea what's <img> size in the page is gonna be. To load it as quickly as possible (before layout is done and even before any CSS is downloaded) we need to provide sizes attribute to hint browser how large is image gonna be:

<img src="clock-demo-thumb-200.png" alt="Clock" srcset="clock-demo-thumb-200.png 200w, clock-demo-thumb-400.png 400w" sizes="(max-width: 600px) 200px, 50vw">

Unfortunately, sizes attribute is frequently forgotten by developers making websites load too large images (sizes defaults to 100vw).

However, sizes attribute is extremely redundant in most cases!. If image can be loaded after layout phase (most below-the-fold images can), the browser already knows its size so it could pick best image based on srcset only without sizes at all.

I have a feeling that if loading=lazy images are loaded after layout phase is done (how else can you know it's in viewport?), sizes parameter remains reasonable only for images loaded eagerly (not too many of them).

My suggestion is that sizes parameter should be ignored by browser when image is loaded after its size in layout is calculated by browsers. Instead, browsers automatically pick the best version of image from srcset.

I believe it would reduce a huge amount of mistakes being caused by lack of sizes attribute (which is de facto duplication of CSS logic, because CSS already says how big image will be). The most ridiculous situation (and common one) is when image sits in a grid (let's say 4 items in a row, so it's 350px wide in 1920px browser), is below-the-fold, it's loaded 10 seconds after page is loaded, it is obvious at this point in time it's 350px wide. And browsers still download 1920px version from srcset because sizes is not there. Very unnecessary in my opinion.

@mathiasbynens

This comment has been minimized.

Copy link
Member

commented May 7, 2019

Have anyone considered how does loading="lazy" affect responsive images and srcset and sizes attributes?

It just works. The loading attribute goes on the <img>, and whichever of the srcset (or <source>) images the browser decides to use, are then lazily loaded.

@zcorpan

This comment has been minimized.

Copy link
Member

commented May 8, 2019

@r00dY I believe what you're asking for is essentially the data-sizes="auto" feature in lazySizes. I think this has been discussed before (maybe somewhere in https://github.com/ResponsiveImagesCG/picture-element/issues ), though I can't find it now. It was blocked on native lazy loading, but that is being introduced in this PR, so you're right that it is good timing to revisit "auto sizes".

Can you file a new issue?

@AmeliaBR

This comment has been minimized.

Copy link

commented May 21, 2019

Has there been any consideration of how this does/should affect alt text display?

Alt text is displayed as visible content when images fail to load, or when users have disabled image loading. But when image loading is active, I believe most user agents currently wait until they've tried to load an image before displaying the alt.

My personal opinion: if the lazy loaded image will be fetched automatically when it comes into view, it's reasonable to delay display of the alt text until the fetch has timed out or returned an error. But if the image won't be fully fetched unless triggered by the user, it may be helpful to display the alt text to help the user decide if the image will be worth the data charges.

Which brings up another question:
Has there been any consideration of how/if this attribute works with user-triggered lazy loading? (Assuming some browser-side user setting to enable this, as an alternative to completely disabling image downloads.) The image fetching algorithms don't seem to leave room for the browser to defer fetching of an on-screen image.

@zcorpan

This comment has been minimized.

Copy link
Member

commented May 21, 2019

Fetching images on-demand by the user is distinct from lazy (but still automatic) loading, and something that the spec has supported for a long time.

When to show the alt is defined in the rendering section, but it has some known bugs, and it's not clear to me which case a load-on-demand image falls into.

https://html.spec.whatwg.org/multipage/rendering.html#images-3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.