Add native loading=lazy support for video elements#2450
Add native loading=lazy support for video elements#2450adamsilverstein wants to merge 1 commit intotrunkfrom
Conversation
Add loading="lazy" as a progressive enhancement for video elements that are below the fold, alongside the existing JavaScript-based lazy loading. For LCP and visible videos, remove any existing loading attribute to prevent unintended lazy loading. This leverages the new HTML spec support for loading="lazy" on video elements (whatwg/html#10376) while keeping the JS IntersectionObserver fallback for browsers that don't yet support it.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## trunk #2450 +/- ##
==========================================
+ Coverage 69.33% 69.36% +0.02%
==========================================
Files 90 90
Lines 7749 7755 +6
==========================================
+ Hits 5373 5379 +6
Misses 2376 2376
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
I verified this worked as expected on a test page in my local. Non LCP video tags get the lazy loading attribute: <figure class="wp-block-video"><video class="od-lazy-video" data-od-added-class data-od-added-data-original-preload data-od-added-loading data-od-added-preload data-od-xpath="/HTML/BODY/DIV[@id='page']/*[3][self::DIV]/*[1][self::DIV]/*[1][self::MAIN]/*[1][self::ARTICLE]/*[1][self::DIV]/*[12][self::FIGURE]/*[1][self::VIDEO]" data-original-preload="default" loading="lazy" preload="none" height="904" style="aspect-ratio: 1392 / 904;" width="1392" controls src="https://wpdev.localhost/wp-content/uploads/2026/04/inner-button-turns-to-save.mp4"></video></figure> |
Summary
Closes #2400.
loading="lazy"as a progressive enhancement for<video>elements that are below the fold (intersectionRatio = 0), alongside the existing JavaScript IntersectionObserver-based lazy loadingloadingattribute from LCP videos and visible videos to prevent unintended lazy loadingod-lazy-videoclass,data-original-*attributes,lazy-load-video.js) since browser support forloading="lazy"on video is still rolling outThis leverages the new HTML spec support for
loading="lazy"on video elements (whatwg/html#10376). In unsupported browsers, the attribute is simply ignored (zero cost). Audio tag support is deferred to a separate PR.Test plan
loading="lazy"alongside JS lazy loadingloading="lazy"has the attribute removedloading="lazy"has the attribute removedAI Usage
I used Claude code to write the code and tests for this PR which I reviewed. It should probably be manually tested as well, I have not done that yet. The PR is mostly test cases, the code change itself is minor.