Skip to content

Add support for video and audio element lazy-loading via the loading attribute#11980

Open
scottjehl wants to merge 20 commits intowhatwg:mainfrom
Squarespace:video-loading-attribute
Open

Add support for video and audio element lazy-loading via the loading attribute#11980
scottjehl wants to merge 20 commits intowhatwg:mainfrom
Squarespace:video-loading-attribute

Conversation

@scottjehl
Copy link

@scottjehl scottjehl commented Dec 2, 2025

Specify support for the loading attribute for the video element and audio element using similar conventions to img and iframe, where the attribute already has precedent. Loading has possible values of eager and lazy. When a media element's loading attribute value is lazy, loading of any video or poster image data, as well as autoplay playback, will defer until layout is known and the video is in the viewport.

Note Jan 22, 2026: Broadening PR to include Audio Element support.

Resolves #10376

(See WHATWG Working Mode: Changes for more details.)


/acknowledgements.html ( diff )
/indices.html ( diff )
/media.html ( diff )
/urls-and-fetching.html ( diff )

Specify support for the loading attribute for video using similar conventions
to img and iframe, where the attribute has precedent. It has possible values
of eager and lazy. When the loading attribute value is lazy, loading of any
video or poster image data, as well as autoplay playback, must defer until
layout is known and the video is in the viewport. This commit contains examples
for how the loading attribute should take precedence over the preload, poster,
and autoplay attributes. These were informed by experiments with local patch
implementations to several user agents.
@annevk annevk added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: media needs tests Moving the issue forward requires someone to write tests labels Dec 4, 2025
@annevk
Copy link
Member

annevk commented Dec 4, 2025

cc @whatwg/media

@foolip
Copy link
Member

foolip commented Dec 9, 2025

This direction makes sense to me, but I'm not personally able to make a commitment to implement in Chromium.

@zcorpan I think you've mentioned this feature, perhaps you have feedback?

Add detail for video element lazy loading behavior when loading state is lazy.
This involves returning early to prevent poster and video data loading and
defining resumption steps to resume when loading state changes to eager. Also
includes notes about autoplay eligibility and precedence over the preload attribute.
Adjust language of this statement about precedence of the loading
attribute over the preload attribute so that it reiterates a fact.
Remove mention as audio is not mentioned in this proposed attribute addition
scottjehl added a commit to Squarespace/wpt that referenced this pull request Jan 7, 2026
…g attribute

These tests support the proposal for the addition of a loading attribute
on the video element, designed to enable lazy-loading for video and poster
data. HTML Standard PR here whatwg/html#11980

Co-authored-by: Zach Lysobey <zlysobey@squarespace.com>
Co-authored-by: Brad Frost <bfrost@squarespace.com>
Co-authored-by: Credo Duarte <cduarte@squarespace.com>
@scottjehl
Copy link
Author

Added and linked up a PR with web platform tests web-platform-tests/wpt#57051

small note: it says my entity is unverified above, but I think it's registered correctly now and needs a check

@zcorpan zcorpan removed needs implementer interest Moving the issue forward requires implementers to express interest needs tests Moving the issue forward requires someone to write tests labels Jan 14, 2026
@scottjehl scottjehl requested a review from zcorpan January 14, 2026 17:41
@zcorpan
Copy link
Member

zcorpan commented Jan 15, 2026

@scottjehl I tried to push changes to this branch but was denied. Can you enable "Allow edits from maintainers"?

@scottjehl
Copy link
Author

@zcorpan I looked into how to do that and it sounds like the option may not be available for forks made by an organization, such as this one. Any other way we can help? Perhaps if the changes are in a public fork of yours I could pull them from there?

@zcorpan
Copy link
Member

zcorpan commented Jan 16, 2026

@scottjehl OK, pushed to https://github.com/zcorpan/html/tree/video-loading-attribute

@scottjehl
Copy link
Author

@zcorpan looked great, thanks. Merged here!

credod added a commit to Squarespace/WebKit that referenced this pull request Feb 12, 2026
…ttribute

https://bugs.webkit.org/show_bug.cgi?id=303995

Reviewed by NOBODY (OOPS!).

Implement proposed loading attribute for video and audio elements.
This patch implements a proposed loading attribute for video and audio elements, enabling lazy loading of media sources and video poster images, and deferring autoplay.

This change is proposed to be added to the HTML spec in the following PR:
whatwg/html#11980

This patch is passing video and audio WPT tests from the following PR:
web-platform-tests/wpt#57051

* Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml:
* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::lazyLoadMediaObserver):
* Source/WebCore/dom/Document.h:
* Source/WebCore/html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::didMoveToNewDocument):
(WebCore::HTMLMediaElement::attributeChanged):
(WebCore::HTMLMediaElement::didFinishInsertingNode):
(WebCore::HTMLMediaElement::removedFromAncestor):
(WebCore::HTMLMediaElement::hasLazyLoadableAttributeValue):
(WebCore::HTMLMediaElement::isLazyLoadable const):
(WebCore::HTMLMediaElement::loadDeferredMedia):
(WebCore::HTMLMediaElement::resumeLazyLoadingIfNeeded):
(WebCore::HTMLMediaElement::loading const):
(WebCore::HTMLMediaElement::setLoading):
(WebCore::HTMLMediaElement::play):
(WebCore::HTMLMediaElement::sourceWasAdded):
(WebCore::HTMLMediaElement::setShouldDelayLoadEvent):
* Source/WebCore/html/HTMLMediaElement.h:
* Source/WebCore/html/HTMLMediaElement.idl:
* Source/WebCore/html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::rendererIsNeeded):
(WebCore::HTMLVideoElement::supportsFullscreen const):
(WebCore::HTMLVideoElement::hasAvailableVideoFrame const):
(WebCore::HTMLVideoElement::webkitEnterFullscreen):
(WebCore::HTMLVideoElement::loadDeferredMedia):
* Source/WebCore/html/HTMLVideoElement.h:
* Source/WebCore/html/LazyLoadMediaObserver.cpp: Added.
(WebCore::LazyLoadMediaObserver::observe):
(WebCore::LazyLoadMediaObserver::unobserve):
(WebCore::LazyLoadMediaObserver::intersectionObserver):
(WebCore::LazyLoadMediaObserver::isObserved const):
* Source/WebCore/html/LazyLoadMediaObserver.h: Added.
* Source/WebCore/html/parser/HTMLParserOptions.cpp:
* Source/WebCore/html/parser/HTMLPreloadScanner.cpp:
(WebCore::TokenPreloadScanner::StartTagScanner::processAttribute):
* Source/WebCore/html/shadow/DataListButtonElement.cpp:
* Source/WebCore/html/shadow/SpinButtonElement.cpp:
* Source/WebCore/loader/ImageLoader.cpp:
(WebCore::ImageLoader::updateFromElement):
(WebCore::ImageLoader::didUpdateCachedImage):
(WebCore::ImageLoader::notifyFinished):
(WebCore::ImageLoader::updatedHasPendingEvent):
(WebCore::ImageLoader::decode):
@bkimmelSQSP
Copy link

bkimmelSQSP commented Feb 17, 2026

Are there any known outstanding issues preventing this from advancing to Stage 2?

credod added a commit to Squarespace/WebKit that referenced this pull request Feb 17, 2026
…ttribute

https://bugs.webkit.org/show_bug.cgi?id=303995

Reviewed by NOBODY (OOPS!).

Implement proposed loading attribute for video and audio elements.
This patch implements a proposed loading attribute for video and audio elements, enabling lazy loading of media sources and video poster images, and deferring autoplay.

This change is proposed to be added to the HTML spec in the following PR:
whatwg/html#11980

This patch is passing video and audio WPT tests from the following PR:
web-platform-tests/wpt#57051

* Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml:
* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::lazyLoadMediaObserver):
* Source/WebCore/dom/Document.h:
* Source/WebCore/html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::didMoveToNewDocument):
(WebCore::HTMLMediaElement::attributeChanged):
(WebCore::HTMLMediaElement::didFinishInsertingNode):
(WebCore::HTMLMediaElement::removedFromAncestor):
(WebCore::HTMLMediaElement::hasLazyLoadableAttributeValue):
(WebCore::HTMLMediaElement::isLazyLoadable const):
(WebCore::HTMLMediaElement::loadDeferredMedia):
(WebCore::HTMLMediaElement::resumeLazyLoadingIfNeeded):
(WebCore::HTMLMediaElement::loading const):
(WebCore::HTMLMediaElement::setLoading):
(WebCore::HTMLMediaElement::play):
(WebCore::HTMLMediaElement::sourceWasAdded):
(WebCore::HTMLMediaElement::setShouldDelayLoadEvent):
* Source/WebCore/html/HTMLMediaElement.h:
* Source/WebCore/html/HTMLMediaElement.idl:
* Source/WebCore/html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::rendererIsNeeded):
(WebCore::HTMLVideoElement::supportsFullscreen const):
(WebCore::HTMLVideoElement::hasAvailableVideoFrame const):
(WebCore::HTMLVideoElement::webkitEnterFullscreen):
(WebCore::HTMLVideoElement::loadDeferredMedia):
* Source/WebCore/html/HTMLVideoElement.h:
* Source/WebCore/html/LazyLoadMediaObserver.cpp: Added.
(WebCore::LazyLoadMediaObserver::observe):
(WebCore::LazyLoadMediaObserver::unobserve):
(WebCore::LazyLoadMediaObserver::intersectionObserver):
(WebCore::LazyLoadMediaObserver::isObserved const):
* Source/WebCore/html/LazyLoadMediaObserver.h: Added.
* Source/WebCore/html/parser/HTMLParserOptions.cpp:
* Source/WebCore/html/parser/HTMLPreloadScanner.cpp:
(WebCore::TokenPreloadScanner::StartTagScanner::processAttribute):
* Source/WebCore/html/shadow/DataListButtonElement.cpp:
* Source/WebCore/html/shadow/SpinButtonElement.cpp:
* Source/WebCore/loader/ImageLoader.cpp:
(WebCore::ImageLoader::updateFromElement):
(WebCore::ImageLoader::didUpdateCachedImage):
(WebCore::ImageLoader::notifyFinished):
(WebCore::ImageLoader::updatedHasPendingEvent):
(WebCore::ImageLoader::decode):
credod added a commit to Squarespace/WebKit that referenced this pull request Feb 18, 2026
…ttribute

https://bugs.webkit.org/show_bug.cgi?id=303995

Reviewed by NOBODY (OOPS!).

Implement proposed loading attribute for video and audio elements.
This patch implements a proposed loading attribute for video and audio elements, enabling lazy loading of media sources and video poster images, and deferring autoplay.

This change is proposed to be added to the HTML spec in the following PR:
whatwg/html#11980

This patch is passing video and audio WPT tests from the following PR:
web-platform-tests/wpt#57051

* Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml:
* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::lazyLoadMediaObserver):
* Source/WebCore/dom/Document.h:
* Source/WebCore/html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::didMoveToNewDocument):
(WebCore::HTMLMediaElement::attributeChanged):
(WebCore::HTMLMediaElement::didFinishInsertingNode):
(WebCore::HTMLMediaElement::removedFromAncestor):
(WebCore::HTMLMediaElement::hasLazyLoadableAttributeValue):
(WebCore::HTMLMediaElement::isLazyLoadable const):
(WebCore::HTMLMediaElement::loadDeferredMedia):
(WebCore::HTMLMediaElement::resumeLazyLoadingIfNeeded):
(WebCore::HTMLMediaElement::loading const):
(WebCore::HTMLMediaElement::setLoading):
(WebCore::HTMLMediaElement::play):
(WebCore::HTMLMediaElement::sourceWasAdded):
(WebCore::HTMLMediaElement::setShouldDelayLoadEvent):
* Source/WebCore/html/HTMLMediaElement.h:
* Source/WebCore/html/HTMLMediaElement.idl:
* Source/WebCore/html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::rendererIsNeeded):
(WebCore::HTMLVideoElement::supportsFullscreen const):
(WebCore::HTMLVideoElement::hasAvailableVideoFrame const):
(WebCore::HTMLVideoElement::webkitEnterFullscreen):
(WebCore::HTMLVideoElement::loadDeferredMedia):
* Source/WebCore/html/HTMLVideoElement.h:
* Source/WebCore/html/LazyLoadMediaObserver.cpp: Added.
(WebCore::LazyLoadMediaObserver::observe):
(WebCore::LazyLoadMediaObserver::unobserve):
(WebCore::LazyLoadMediaObserver::intersectionObserver):
(WebCore::LazyLoadMediaObserver::isObserved const):
* Source/WebCore/html/LazyLoadMediaObserver.h: Added.
* Source/WebCore/html/parser/HTMLParserOptions.cpp:
* Source/WebCore/html/parser/HTMLPreloadScanner.cpp:
(WebCore::TokenPreloadScanner::StartTagScanner::processAttribute):
* Source/WebCore/html/shadow/DataListButtonElement.cpp:
* Source/WebCore/html/shadow/SpinButtonElement.cpp:
* Source/WebCore/loader/ImageLoader.cpp:
(WebCore::ImageLoader::updateFromElement):
(WebCore::ImageLoader::didUpdateCachedImage):
(WebCore::ImageLoader::notifyFinished):
(WebCore::ImageLoader::updatedHasPendingEvent):
(WebCore::ImageLoader::decode):
@scottjehl
Copy link
Author

Updated the issue to note

  • the feature just merged in Chromium behind a feature flag.
  • Added an MDN issue and checked the box as done

@scottjehl
Copy link
Author

Added a bulletpoint for our WebKit Patch, currently in Review: WebKit/WebKit#58220

credod added a commit to Squarespace/WebKit that referenced this pull request Feb 24, 2026
…ttribute

https://bugs.webkit.org/show_bug.cgi?id=303995

Reviewed by NOBODY (OOPS!).

Implement proposed loading attribute for video and audio elements.
This patch implements a proposed loading attribute for video and audio elements, enabling lazy loading of media sources and video poster images, and deferring autoplay.

This change is proposed to be added to the HTML spec in the following PR:
whatwg/html#11980

This patch is passing video and audio WPT tests from the following PR:
web-platform-tests/wpt#57051

* Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml:
* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::lazyLoadMediaObserver):
* Source/WebCore/dom/Document.h:
* Source/WebCore/html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::didMoveToNewDocument):
(WebCore::HTMLMediaElement::attributeChanged):
(WebCore::HTMLMediaElement::didFinishInsertingNode):
(WebCore::HTMLMediaElement::removedFromAncestor):
(WebCore::HTMLMediaElement::hasLazyLoadableAttributeValue):
(WebCore::HTMLMediaElement::isLazyLoadable const):
(WebCore::HTMLMediaElement::loadDeferredMedia):
(WebCore::HTMLMediaElement::resumeLazyLoadingIfNeeded):
(WebCore::HTMLMediaElement::loading const):
(WebCore::HTMLMediaElement::setLoading):
(WebCore::HTMLMediaElement::play):
(WebCore::HTMLMediaElement::sourceWasAdded):
(WebCore::HTMLMediaElement::setShouldDelayLoadEvent):
* Source/WebCore/html/HTMLMediaElement.h:
* Source/WebCore/html/HTMLMediaElement.idl:
* Source/WebCore/html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::rendererIsNeeded):
(WebCore::HTMLVideoElement::supportsFullscreen const):
(WebCore::HTMLVideoElement::hasAvailableVideoFrame const):
(WebCore::HTMLVideoElement::webkitEnterFullscreen):
(WebCore::HTMLVideoElement::loadDeferredMedia):
* Source/WebCore/html/HTMLVideoElement.h:
* Source/WebCore/html/LazyLoadMediaObserver.cpp: Added.
(WebCore::LazyLoadMediaObserver::observe):
(WebCore::LazyLoadMediaObserver::unobserve):
(WebCore::LazyLoadMediaObserver::intersectionObserver):
(WebCore::LazyLoadMediaObserver::isObserved const):
* Source/WebCore/html/LazyLoadMediaObserver.h: Added.
* Source/WebCore/html/parser/HTMLParserOptions.cpp:
* Source/WebCore/html/parser/HTMLPreloadScanner.cpp:
(WebCore::TokenPreloadScanner::StartTagScanner::processAttribute):
* Source/WebCore/html/shadow/DataListButtonElement.cpp:
* Source/WebCore/html/shadow/SpinButtonElement.cpp:
* Source/WebCore/loader/ImageLoader.cpp:
(WebCore::ImageLoader::updateFromElement):
(WebCore::ImageLoader::didUpdateCachedImage):
(WebCore::ImageLoader::notifyFinished):
(WebCore::ImageLoader::updatedHasPendingEvent):
(WebCore::ImageLoader::decode):
@scottjehl
Copy link
Author

@zcorpan While refining our Firefox patch, we noticed that this spec may need to describe what happens when video methods such as play() and load() are called explicitly when loading is in the lazy state. We think such methods should take precedence over the loading attribute. Should this be in the spec?

@cwilso cwilso added stage: 2 Iteration and removed stage: 1 Incubation labels Feb 26, 2026
@scottjehl
Copy link
Author

A couple revisions today:

  • Made some updates to decouple poster and source resumption steps.
  • specified that load() and play() methods should override loading attr.

Curious to hear if these resolve the issues we'd discussed.
Thanks all.

source Outdated
data-x="dom-media-play">play()</code> methods take precedence over the <code
data-x="attr-media-loading">loading</code> attribute. When these methods are invoked, the user agent
must allow associated data loading and playback to proceed, regardless of the <code
data-x="attr-media-loading">loading</code> attribute's state.</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit action at a distance, and should be formalized in the relevant algorithms what exactly is expected.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I gave it a shot. Over on the load() and play() methods.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. This paragraph should be removed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great. Done.

@scottjehl scottjehl requested a review from zcorpan March 5, 2026 01:02
source Outdated
Comment on lines +40169 to +40180
<li><p>Let <var>resumptionSteps</var> be the <span>media element</span>'s <span>lazy load
resumption steps</span>.</p></li>

<li><p>If <var>resumptionSteps</var> is not null, then:</p>

<ol>
<li><p>Set the <span>media element</span>'s <span>lazy load resumption steps</span> to null.</p></li>

<li><p>Invoke <var>resumptionSteps</var>.</p></li>
</ol>
</li>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be moved down after the error-checking steps, so it's right before the step creating promise.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks that makes sense. I moved it down.

@scottjehl scottjehl requested a review from zcorpan March 5, 2026 18:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

addition/proposal New features or enhancements stage: 2 Iteration topic: media

Development

Successfully merging this pull request may close these issues.

Video and Audio Element loading=lazy attribute support

10 participants