html icon indicating copy to clipboard operation
html copied to clipboard

Video loading=lazy attribute support

Open scottjehl opened this issue 1 year ago • 1 comments

What is the issue with the HTML Standard?

If the video element offered loading="lazy" support, that attribute could be used to determine how other desirable video features behave, such as when autoplay starts playing, and when its poster image and video file data are fetched.

For example, loading=lazy combined with the autoplay attribute could cause a video to delay its poster image loading, its data fetching (other than metadata perhaps?), and its autoplay behavior until the video element is in (near) the viewport. Per my understanding, lazy autoplay is currently doable with JavaScript and it'd be great to offer a declarative HTML alternative.

Could <video loading="lazy" ..></video> be one already-familiar way to offer a set of lazy behaviors for video?

scottjehl avatar May 29 '24 19:05 scottjehl

Huge fan of this, as it becomes more standard like img.

Had this convo via Slack with @tunetheweb and others.

Seems like logic could make multiple things happen as you describe:

  • preload="none" loading="lazy" poster="/image.jpg" would do nothing until the user scrolls near, then would load the poster and begin downloading the video; without autoplay the user would need to initiate playing.
  • preload="none" loading="lazy" autoplay poster="/image.jpg" would do nothing until the user scrolls near, then would load the poster and begin downloading the video; once the video is downloaded, begin playing.
  • preload="metadata" loading="lazy" autoplay poster="/image.jpg" would only download metadata nothing until the user scrolls near, then would load the poster and begin downloading the video; once the video is downloaded, begin playing.
  • etc.

It bugs me that JS is required to autoplay lazy loaded videos... :-/

aarontgrogg avatar May 29 '24 19:05 aarontgrogg

/sub and +1

Went hunting for why video can't lazy load and found this. On my site nerdy.dev there is a lot of savings potential. I use preload="none" right now, which saves a lot already, but all the poster images still download, even the ones way at the bottom. Would like to save that bandwidth and not use JS for this type of optimization.

argyleink avatar Jan 22 '25 19:01 argyleink

cc @whatwg/media

annevk avatar Jan 23 '25 09:01 annevk

My previous comment about options: https://github.com/whatwg/html/issues/6636#issuecomment-1125404102

I suppose a reason to want lazy-loading for videos (over preload="none" and some way to opt in to lazy-loading for the poster image) is when you don't have a poster image. Or you want some video data to be loaded (when scrolled into view) so that playback starts sooner when requested.

zcorpan avatar Jan 23 '25 10:01 zcorpan

@argyleink : The closest thing to ideal that I have found (I did not create this, but cannot find who I pilfered from) is something like this for above-the-fold videos with "posters"...

<section class="video-wrapper">
    <picture>
        <source srcset="poster-image-mobile.png" height="1080" width="1920" media="(max-width: 1023px)">
        <source srcset="poster-image-desktop.png" height="1920" width="1080" media="(min-width: 1024px)">
        <img src="" loading="eager" alt="Descriptive text">
    </picture>
    <video preload="auto" autoplay muted loop playsinline controlslist="nodownload">
        <source src="video-mobile.mp4" height="1080" width="1920" type="video/mp4" media="(max-width: 1023px)">
        <source src="video-desktop.mp4" height="1920" width="1080" type="video/mp4" media="(min-width: 1024px)">
    </video>
</section>

And can then add:

<link rel="preload" fetchpriority="high" as="image" href="poster-image-mobile.png" media="(max-width: 1023px)">
<link rel="preload" fetchpriority="high" as="image" href="poster-image-desktop.png" media="(min-width: 1024px)">

And position the video over the picture with:

<style>
    img, video {
        max-width: 100%;
        width: 100%;
        height: auto;
    }
    .video-wrapper {
        display: grid;
        grid-template: "container";
        place-items: center;
        place-content: center;
    }
    .video-wrapper > picture,
    .video-wrapper > video {
        grid-area: container;
    }
    .video-wrapper img {
        width: 100%;
        height: auto;
        object-fit: cover;
    }
</style>

For below-the-fold:

  • change the img loading to "lazy",
  • change the video preload to "none",
  • remove the video autoplay and
  • remove the "preload" links.

Bit verbose, but gets the job done:

  • Above-the-fold: Correct image preloads based on media, so is visible fast, as video downloads, just starts playing over top. If the poster image is the first frame of the video, it looks like it is kind of "stuck', then just starts playing, but you see something soon.
  • Below-the-fold: Correct image lazy loads based on media, so is visible when the user scrolls to it, the video downloads if the user click it, and just starts playing over top.

Massive kudos to whoever initially came up with this.

aarontgrogg avatar Jan 24 '25 15:01 aarontgrogg

Could I fly an API proposal that (I believe) is both not too hard to implement and targets all use cases raised here (except poster, which is covered by https://github.com/whatwg/html/issues/6636)?

Tl;dr I’d like lazy loading to cover two scenarios: 1) delaying prefetch requests for videos that are outside of the viewport; 2) delaying playback for autoplaying muted videos (aka video “gifs”) that are outside of the viewport. (Both of these are something we had to build custom IntersectionObserver solutions for at Framer.)

I think this is reasonably solved with two new attributes:

  • loading="lazy": acts similarly to a trivial user-land IntersectionObserver, switching between preload="none" and the specified value of preload based on whether the video is ~within the viewport
  • autoplay="in-viewport": a new value for the existing autoplay attribute, indicating that the video must play only within the viewport

I feel these primitives combine really well and also allow covering other scenarios as well, such as eg a news article where a relevant video starts playing when you scroll to it.

iamakulov avatar Oct 31 '25 17:10 iamakulov

I agree with @iamakulov and would also like to suggest that lazy-loading poster images would be good to include with this as well.

Are implementations/patches helpful at this stage or does the spec need to lead on behavior? Thanks.

scottjehl avatar Nov 03 '25 21:11 scottjehl

For autoplay="in-viewport", I see https://github.com/whatwg/html/issues/2364 and https://github.com/whatwg/html/issues/9793

zcorpan avatar Nov 10 '25 02:11 zcorpan

Are implementations/patches helpful at this stage or does the spec need to lead on behavior? Thanks.

Experimental implementations (e.g. behind a pref) are OK and could help with finding issues or move things forward. It also signals implementer interest.

zcorpan avatar Nov 10 '25 02:11 zcorpan

For autoplay="in-viewport", I see #2364 and #9793

It seems to me that autoplay would need to wait alongside loading=lazy anyway to avoid negating its effects (by needing to load the video too early in order to start playing it). Along those lines, it makes sense for autoplay to pend on the same timing as loading=lazy when it's present, I think. Is that a fair assumption?

(additional autoplay values could be useful in other cases I suppose, but it seems like autoplay should depend on loading=lazy when it's present)

scottjehl avatar Nov 10 '25 12:11 scottjehl

Following up! My team at Squarespace has been exploring the possibility of contributing one or more browser patches, Web Platform Tests, and proposed edits to the HTML standard to help move this feature along. We think it'll bring nice performance benefits. We hope to contribute some or all of the above in the near future, assuming that's helpful.

Based on our work with these so far, I wanted to add a few questions relevant to the HTML standard portion:

  • The HTML spec currently says that the video autoplay attribute may cause a video to begin playing either immediately at page load or when a video intersects with/near the viewport (and is thus, visible). It doesn't recommend one or the other (which is fair enough) though we've noticed that both Chromium and Webkit seem to usually defer autoplay until an element intersects, and we think that behavior feels expected and nice. After working with video loading=lazy however, we do think that the standard should probably recommend deferring autoplay in this manner more firmly when a video element has the loading=lazy attribute. Otherwise, autoplay may introduce data fetching that could override the lazy loading behavior. Since this deferral behavior is not present in Firefox currently, the draft Firefox patch we’ve been exploring includes the autoplay deferral when loading=lazy is present on a video, and it seems to match our expectations from a user perspective. Would this make sense to mention in the standard?
  • As other comments above mention, when loading=lazy is present on a video element, we think it makes sense to defer poster image downloads in addition to a video's source data. Implementation-wise, this will mean that the preload scanner needs to avoid early-fetches of poster images based on this attribute’s value as well, when applicable. Do we agree that poster should be deferred along with video data when loading is lazy?
  • When the loading attribute is present and has a lazy value, we think its behavior should take priority over anything specified in the preload attribute as well during page load. The preload attribute should still control what is preloaded whenever the video begins loading data in general (eg upon viewport intersection). Does this sound okay?

Thanks for the feedback on those.

Also, if we are able to send a PR to this repo suggesting edits to the standard to support his attribute for video, would that be welcome? Should any Web Platform Tests we contribute (as Pull Requests) be linked to this PR if we are able to make it?

Thanks!

scottjehl avatar Nov 19 '25 18:11 scottjehl

@scottjehl :

  • Point 1: Yeah, seems like this should be normalized, ideally via spec, and if Chromium and WebKit already do it that way, seems to make sense to use that, and hope for others to implement consistently.
  • Point 2: Yes, seems like it makes sense to parallel poster download with video download, though for delayed loading, I would make a case that skipping the poster would be smarter, so it doesn't interfere/delay the actual video trying to download, but that's a "best practices" issue, not an implementation one... ;-)
  • Point 3: Like the idea that "[t]he preload attribute should still control what is preloaded"; I think all that really needs to change is that the auto behavior should now defer to the loading attribute, if it is present, right?

I would love to be able to use preload="metadata" loading="lazy" and have the browser preload only the metadata, then load the video/poster only when nearing the viewport intersection, but in discussions with Scott, it sounds like this is not going to do what I would want, consistently across browsers, so maybe delaying the preload there also makes more sense... (Unless browser start actually reducing what they download with metadata... 😉)

That's my 2 bits...

aarontgrogg avatar Nov 19 '25 18:11 aarontgrogg

There seems to be quite a lot of different states and conbinations to consider. I couldn't help myself but had to write it down.

Let's start with when a video should start playing (assuming browser's auto-play constraints are met):

  • if autoplay attribute specified with any string except "lazy": play video on page load
  • autoplay="lazy": only start playing when in viewport
  • no autoplay attribute (or autoplay="none" if we want to be consistent with below): video needs to be started manually by clicking it

Now, if the video is not already playing, we still have the choice of when to load the video:

  • preload="auto": preload video on page load
  • preload="lazy": preload video when in viewport
  • preload="none": do not preload video

And finally, if the video is still not preloading, we now still have the choice of when to load the poster and metadata. So if we want to have this completely configurable, we need two new attributes, preloadposter and preloadmetadata, that each can be set to lazy or not. (Default should be whatever current implementations do.)

The above seems all compatible with the current standard, except for the existing preload="metadata". That would have to be carefully reasoned about what whould take precedence.

And of course there's the question whether we want this kind of configurability. But it seems that sooner or later someone will propose to add it either way, so might as well think through all cases from the beginning.

mb21 avatar Nov 20 '25 08:11 mb21