Skip to content

Add native loading=lazy support for video elements#2450

Open
adamsilverstein wants to merge 1 commit intotrunkfrom
add-native-video-support
Open

Add native loading=lazy support for video elements#2450
adamsilverstein wants to merge 1 commit intotrunkfrom
add-native-video-support

Conversation

@adamsilverstein
Copy link
Copy Markdown
Member

@adamsilverstein adamsilverstein commented Apr 9, 2026

Summary

Closes #2400.

  • Adds loading="lazy" as a progressive enhancement for <video> elements that are below the fold (intersectionRatio = 0), alongside the existing JavaScript IntersectionObserver-based lazy loading
  • Removes any existing loading attribute from LCP videos and visible videos to prevent unintended lazy loading
  • Keeps the JS fallback (od-lazy-video class, data-original-* attributes, lazy-load-video.js) since browser support for loading="lazy" on video is still rolling out

This 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

  • Verify existing snapshot tests pass with updated expected outputs
  • New test: hidden video gets loading="lazy" alongside JS lazy loading
  • New test: visible video with loading="lazy" has the attribute removed
  • New test: LCP video with loading="lazy" has the attribute removed
  • PHPStan passes at level 10

AI 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.

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
Copy link
Copy Markdown

codecov bot commented Apr 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.36%. Comparing base (8d1741e) to head (39f797e).

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              
Flag Coverage Δ
multisite 69.36% <100.00%> (+0.02%) ⬆️
single 35.70% <0.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@adamsilverstein adamsilverstein added the [Type] Feature A new feature within an existing module label Apr 10, 2026
@adamsilverstein adamsilverstein marked this pull request as ready for review April 10, 2026 21:10
@github-actions
Copy link
Copy Markdown

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 props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org>
Co-authored-by: westonruter <westonruter@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@adamsilverstein adamsilverstein self-assigned this Apr 10, 2026
@adamsilverstein adamsilverstein added [Plugin] Enhanced Responsive Images Issues for the Enhanced Responsive Images plugin (formerly Auto Sizes) [Plugin] Image Prioritizer Issues for the Image Prioritizer plugin (dependent on Optimization Detective) and removed [Plugin] Enhanced Responsive Images Issues for the Enhanced Responsive Images plugin (formerly Auto Sizes) labels Apr 10, 2026
@adamsilverstein
Copy link
Copy Markdown
Member Author

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=&apos;page&apos;]/*[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>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Plugin] Image Prioritizer Issues for the Image Prioritizer plugin (dependent on Optimization Detective) [Type] Feature A new feature within an existing module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add native lazy loading support for HTML video and audio tags

1 participant