Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c719dac
Add loading attribute for audio and video
tunetheweb Mar 13, 2026
fef5851
Fix flaws
tunetheweb Mar 13, 2026
4881ac1
Merge branch 'main' into lazy-load-media-content
tunetheweb Mar 13, 2026
8e102dc
Update files/en-us/learn_web_development/extensions/performance/html/…
tunetheweb Mar 16, 2026
6621187
Update files/en-us/web/api/htmlmediaelement/loading/index.md
tunetheweb Mar 16, 2026
42a35ec
Review feedback
tunetheweb Mar 16, 2026
d228dc5
Merge branch 'main' into lazy-load-media-content
tunetheweb Mar 16, 2026
05339da
More review feedback
tunetheweb Mar 16, 2026
0f4cf99
Merge branch 'lazy-load-media-content' of github.com:tunetheweb/conte…
tunetheweb Mar 16, 2026
5c97ed4
Apply suggestions from code review
tunetheweb Mar 16, 2026
4added1
Merge branch 'lazy-load-media-content' of github.com:tunetheweb/conte…
tunetheweb Mar 16, 2026
1582019
Formatting
tunetheweb Mar 16, 2026
ea78de6
Apply suggestions from code review
tunetheweb Mar 16, 2026
ba8b389
Update files/en-us/web/api/htmlmediaelement/loading/index.md
tunetheweb Mar 17, 2026
055bb22
Update files/en-us/web/performance/guides/lazy_loading/index.md
tunetheweb Mar 17, 2026
bd994b7
Merge branch 'main' into lazy-load-media-content
tunetheweb Mar 17, 2026
2209714
Merge branch 'main' into lazy-load-media-content
tunetheweb Mar 23, 2026
d4b2f0e
Update files/en-us/web/performance/guides/lazy_loading/index.md
tunetheweb Mar 23, 2026
a518968
Merge branch 'main' into lazy-load-media-content
tunetheweb Mar 23, 2026
2f4cd62
Merge branch 'main' into lazy-load-media-content
tunetheweb Mar 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Below is a quick review of best practices, tools, APIs with links to provide mor
- Use a CDN for resources which can reduce load times significantly.
- Compress your resources using [gzip](https://www.gnu.org/software/gzip/), [Brotli](https://github.com/google/brotli), and [Zopfli](https://github.com/google/zopfli).
- Image optimization (use CSS animation, or SVG if possible).
- Lazy loading parts of your application outside the viewport. If you do, have a backup plan for SEO (e.g., render full page for bot traffic); for example, by using the [`loading`](/en-US/docs/Web/HTML/Reference/Elements/img#loading) attribute on the {{HTMLElement("img")}} element
- Lazy loading parts of your application outside the viewport. If you do, have a backup plan for SEO (e.g., render full page for bot traffic); for example, by using the [`loading`](/en-US/docs/Web/HTML/Reference/Elements/img#loading) attribute on the {{HTMLElement("img")}} element, or similarly on {{HTMLElement("iframe")}}, {{HTMLElement("video")}}, {{HTMLElement("audio")}} elements.
- It is also crucial to realize what is really important to your users. It might not be absolute timing, but [user perception](/en-US/docs/Learn_web_development/Extensions/Performance/Perceived_performance).

## Quick Wins
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ Lazy loading has historically been handled using JavaScript, but browsers now ha

See [Browser-level image lazy loading for the web](https://web.dev/articles/browser-level-image-lazy-loading) on web.dev for detailed information.

You can also lazy load video content by using the `preload` attribute. For example:
### Lazy loading video and audio

You can also lazy load video content until the video is played, by using the `preload` attribute. For example:

```html
<video controls preload="none" poster="poster.jpg">
Expand All @@ -152,6 +154,26 @@ You can also lazy load video content by using the `preload` attribute. For examp

Giving `preload` a value of `none` tells the browser to not preload any of the video data before the user decides to play it, which is obviously good for performance. Instead, it will just show the image indicated by the `poster` attribute. Different browsers have different default video loading behavior, so it is good to be explicit.

Giving `preload` a value of `metadata` asks the browser to download the minimal data needed to display the video before playing (for example the length, dimensions, and maybe initial frame).

The `loading` attribute can further enhance lazy loading for videos by deferring loading of any video data, regardless of the `preload` value, as well as deferring loading of the `poster` image, until the video is near the viewport (at which point the `preload` value is used as per usual).

```html
<video controls preload="none" poster="poster.jpg" loading="lazy">
<source src="video.webm" type="video/webm" />
<source src="video.mp4" type="video/mp4" />
</video>
```

This also can be used with audio content:

```html
<audio
controls
src="/shared-assets/audio/t-rex-roar.mp3"
loading="lazy"></audio>
```

See [Fast playback with audio and video preload](https://web.dev/articles/fast-playback-with-preload) on web.dev for detailed information.

## Handling embedded content
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Despite being the largest consumer of bandwidth, the impact of image downloading

### Loading strategy

One of the biggest improvements to most websites is [lazy-loading](/en-US/docs/Web/Performance/Guides/Lazy_loading) images beneath the fold, rather than downloading them all on initial page load regardless of whether a visitor scrolls to see them or not. Browsers provide this natively via the [`loading="lazy"`](/en-US/docs/Web/HTML/Reference/Elements/img#loading) attribute on the `<img>` element, and there are also many client-side JavaScript libraries that can do this.
One of the biggest improvements to most websites is [lazy-loading](/en-US/docs/Web/Performance/Guides/Lazy_loading) images beneath the fold, rather than downloading them all on initial page load regardless of whether a visitor scrolls to see them or not. Browsers provide this natively via the [`loading="lazy"`](/en-US/docs/Web/HTML/Reference/Elements/img#loading) attribute on the `<img>` `<iframe>`, `<video>`, and `<audio>` elements, and there are also many client-side JavaScript libraries that can do this.

Beyond loading a subset of images, you should look into the format of the images themselves:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Here are a few tips and tricks to help improve perceived performance:

To improve perceived performance, minimize the original page load. In other words, download the content the user is going to interact with immediately first, and download the rest after "in the background". The total amount of content downloaded may actually increase, but the user only _waits_ on a very small amount, so the download feels faster.

Separate interactive functionality from content, and load text, styles, and images visible at initial load. Delay, or lazy load, images or scripts that aren't used or visible on the initial page load. Additionally, you should optimize the assets you do load. Images and video should be served in the most optimal format, compressed, and in the correct size.
Separate interactive functionality from content, and load text, styles, and images visible at initial load. Delay, or lazy load, images, iframes, media or scripts that aren't used or visible on the initial page load. Additionally, you should optimize the assets you do load. Images and video should be served in the most optimal format, compressed, and in the correct size.

### Prevent jumping content and other reflows

Expand Down
4 changes: 3 additions & 1 deletion files/en-us/web/api/htmliframeelement/loading/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ browser-compat: api.HTMLIFrameElement.loading

{{APIRef("HTML DOM")}}

The **`loading`** property of the {{domxref("HTMLIFrameElement")}} interface is a string that provides a hint to the {{Glossary("user agent")}} indicating whether the [iframe](/en-US/docs/Web/HTML/Reference/Elements/iframe) should be loaded immediately on page load, or only when it is needed.
The **`loading`** property of the {{domxref("HTMLIFrameElement")}} interface is a string that provides a hint to the browser indicating whether the [iframe](/en-US/docs/Web/HTML/Reference/Elements/iframe) should be loaded immediately on page load, or only when it is needed.

This can be used to optimize the loading of the document's contents.
Iframes that are visible when the page loads can be downloaded immediately (eagerly), while iframes that are likely to be offscreen on initial page load can be downloaded lazily — just before they will appear in the window's {{Glossary("visual viewport")}}.
Expand Down Expand Up @@ -41,6 +41,8 @@ All eagerly loaded iframes in the document must be fetched before the `load` eve

## Examples

### Basic usage

The example below shows how you might define a lazy-loaded iframe and then append it to a `<div>` in the document.
The frame would then only be loaded when the frame about to become visible.

Expand Down
2 changes: 1 addition & 1 deletion files/en-us/web/api/htmlimageelement/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ _Inherits properties from its parent, {{domxref("HTMLElement")}}._
- {{domxref("HTMLImageElement.isMap")}}
- : A boolean value that reflects the [`ismap`](/en-US/docs/Web/HTML/Reference/Elements/img#ismap) HTML attribute, indicating that the image is part of a server-side image map. This is different from a client-side image map, specified using an `<img>` element and a corresponding {{HTMLElement("map")}} which contains {{HTMLElement("area")}} elements indicating the clickable areas in the image. The image _must_ be contained within an {{HTMLElement("a")}} element; see the `ismap` page for details.
- {{domxref("HTMLImageElement.loading")}}
- : A string providing a hint to the browser used to optimize loading the document by determining whether to load the image immediately (`eager`) or on an as-needed basis (`lazy`).
- : A string indicating whether the browser should load the image immediately (`eager`) or when it is needed (`lazy`).
- {{domxref("HTMLImageElement.naturalHeight")}} {{ReadOnlyInline}}
- : Returns an integer value representing the intrinsic height of the image in CSS pixels, if it is available; else, it shows `0`. This is the height the image would be if it were rendered at its natural full size.
- {{domxref("HTMLImageElement.naturalWidth")}} {{ReadOnlyInline}}
Expand Down
4 changes: 3 additions & 1 deletion files/en-us/web/api/htmlimageelement/loading/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ browser-compat: api.HTMLImageElement.loading

{{APIRef("HTML DOM")}}

The **`loading`** property of the {{domxref("HTMLImageElement")}} interface provides a hint to the {{Glossary("user agent")}} on how to handle the loading of the image which is currently outside the window's {{Glossary("visual viewport")}}. This helps to optimize the loading of the document's contents by postponing loading the image until it's expected to be needed, rather than immediately during the initial page load. It reflects the `<img>` element's [`loading`](/en-US/docs/Web/HTML/Reference/Elements/img#loading) content attribute.
The **`loading`** property of the {{domxref("HTMLImageElement")}} interface provides a hint to the browser on how to handle the loading of the image which is currently outside the window's {{Glossary("visual viewport")}}. This helps to optimize the loading of the document's contents by postponing loading the image until it's expected to be needed, rather than immediately during the initial page load. It reflects the `<img>` element's [`loading`](/en-US/docs/Web/HTML/Reference/Elements/img#loading) content attribute.

## Value

A string whose value is one of `eager` or `lazy`. For their meanings, see the HTML [`<img>`](/en-US/docs/Web/HTML/Reference/Elements/img#loading) reference.

## Examples

### Basic usage

The `addImageToList()` function shown below adds a photo thumbnail to a list of items, using lazy-loading to avoid loading the image from the network until it's actually needed.

```js
Expand Down
12 changes: 7 additions & 5 deletions files/en-us/web/api/htmlmediaelement/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ _This interface also inherits properties from its ancestors {{domxref("HTMLEleme
- : Returns a boolean that indicates whether the media element has finished playing.
- {{domxref("HTMLMediaElement.error")}} {{ReadOnlyInline}}
- : Returns a {{domxref("MediaError")}} object for the most recent error, or `null` if there has not been an error.
- {{domxref("HTMLMediaElement.loading")}}
- : A string indicating whether the browser should load the media immediately (`eager`) or when it is needed (`lazy`). See [`<video loading>`](/en-US/docs/Web/HTML/Reference/Elements/video#loading) and [`<audio loading>`](/en-US/docs/Web/HTML/Reference/Elements/audio#loading) HTML attributes for more information.
- {{domxref("HTMLMediaElement.loop")}}
- : A boolean that reflects the [`loop`](/en-US/docs/Web/HTML/Reference/Elements/video#loop) HTML attribute, which indicates whether the media element should start over when it reaches the end.
- {{domxref("HTMLMediaElement.mediaKeys")}} {{ReadOnlyInline}} {{SecureContext_Inline}}
Expand Down Expand Up @@ -96,9 +98,9 @@ These properties are obsolete and should not be used, even if a browser still su
- : A {{domxref("MediaController")}} object that represents the media controller assigned to the element, or `null` if none is assigned.
- {{domxref("HTMLMediaElement.mediaGroup")}} {{Deprecated_Inline}} {{Non-standard_Inline}}
- : A string that reflects the `mediagroup` HTML attribute, which indicates the name of the group of elements it belongs to. A group of media elements shares a common {{domxref('MediaController')}}.
- {{domxref("HTMLMediaElement.mozAudioCaptured")}} {{ReadOnlyInline}} {{Non-standard_Inline}} {{Deprecated_Inline}}
- `HTMLMediaElement.mozAudioCaptured` {{ReadOnlyInline}} {{Non-standard_Inline}} {{Deprecated_Inline}}
- : Returns a boolean. Related to audio stream capture.
- {{domxref("HTMLMediaElement.mozFragmentEnd")}} {{Non-standard_Inline}} {{Deprecated_Inline}}
- `HTMLMediaElement.mozFragmentEnd` {{Non-standard_Inline}} {{Deprecated_Inline}}
- : A `double` that provides access to the fragment end time if the media element has a fragment URI for `currentSrc`, otherwise it is equal to the media duration.

## Instance methods
Expand Down Expand Up @@ -134,9 +136,9 @@ _These methods are obsolete and should not be used, even if a browser still supp

- {{domxref("HTMLMediaElement.captureStream", "HTMLMediaElement.mozCaptureStream()")}} {{Non-standard_Inline}}
- : The Firefox-prefixed equivalent of {{domxref("HTMLMediaElement.captureStream()")}}. See its [browser compatibility](/en-US/docs/Web/API/HTMLMediaElement/captureStream#browser_compatibility) for details.
- {{domxref("HTMLMediaElement.mozCaptureStreamUntilEnded()")}} {{Non-standard_Inline}} {{Deprecated_Inline}}
- : \[enter description]
- {{domxref("HTMLMediaElement.mozGetMetadata()")}} {{Non-standard_Inline}} {{Deprecated_Inline}}
- `HTMLMediaElement.mozCaptureStreamUntilEnded()` {{Non-standard_Inline}} {{Deprecated_Inline}}
- : A non-standard, deprecated, method to capture the steam until it ended.
- `HTMLMediaElement.mozGetMetadata()` {{Non-standard_Inline}} {{Deprecated_Inline}}
- : Returns {{jsxref('Object')}}, which contains properties that represent metadata from the playing media resource as `{key: value}` pairs. A separate copy of the data is returned each time the method is called. This method must be called after the [`loadedmetadata`](/en-US/docs/Web/API/HTMLMediaElement/loadedmetadata_event) event fires.

## Events
Expand Down
62 changes: 62 additions & 0 deletions files/en-us/web/api/htmlmediaelement/loading/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: "HTMLMediaElement: loading property"
short-title: loading
slug: Web/API/HTMLMediaElement/loading
page-type: web-api-instance-property
browser-compat: api.HTMLMediaElement.loading
---

{{APIRef("HTML DOM")}}

The **`loading`** property of the {{domxref("HTMLMediaElement")}} interface provides a hint to the browser on how to handle the loading of the media which is currently outside the window's {{Glossary("visual viewport")}}. This helps to optimize the loading of the document's contents by postponing loading the media until it's expected to be needed, rather than immediately during the initial page load. It reflects the `<audio>` element's [`loading`](/en-US/docs/Web/HTML/Reference/Elements/audio#loading) content attribute or the `<video>` element's [`loading`](/en-US/docs/Web/HTML/Reference/Elements/video#loading) content attribute.

## Value

A string whose value is one of `eager` or `lazy`. For their meanings, see the HTML [`<audio loading>`](/en-US/docs/Web/HTML/Reference/Elements/audio#loading) or [`<video loading>`](/en-US/docs/Web/HTML/Reference/Elements/video#loading) reference.

## Examples

Comment thread
tunetheweb marked this conversation as resolved.
### Basic usage

The `addVideoToList()` function shown below adds a video thumbnail to a list of items, using lazy-loading to avoid loading the video from the network until it's actually needed.

```js
function addVideoToList(url) {
Comment thread
tunetheweb marked this conversation as resolved.
const list = document.querySelector("div.video-list");

const newItem = document.createElement("div");
newItem.className = "video-item";

const newVideo = document.createElement("video");

// Lazy-load if supported
if ("loading" in HTMLVideoElement.prototype) {
newVideo.loading = "lazy";
} else {
// If native lazy-loading is not supported you may want to consider
// alternatives, though this may be fine as a progressive enhancement.
}

newVideo.width = 320;
newVideo.height = 240;
newVideo.src = url;

newItem.appendChild(newVideo);
list.appendChild(newItem);
}
```

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}

## See also

- The {{HTMLElement("audio")}} element
- The {{HTMLElement("video")}} element
- [Web performance](/en-US/docs/Learn_web_development/Extensions/Performance) in the MDN Learning Area
- [Lazy loading](/en-US/docs/Web/Performance/Guides/Lazy_loading) in the MDN web performance guide
2 changes: 1 addition & 1 deletion files/en-us/web/api/window/load_event/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ browser-compat: api.Window.load_event

{{APIRef}}

The **`load`** event is fired when the whole page has loaded, including all dependent resources such as stylesheets, scripts (including async, deferred, and module scripts), iframes, and images, except those that are [loaded lazily](/en-US/docs/Web/Performance/Guides/Lazy_loading#images_and_iframes).
The **`load`** event is fired when the whole page has loaded, including all dependent resources such as stylesheets, scripts (including async, deferred, and module scripts), iframes, and images, except those that are [loaded lazily](/en-US/docs/Web/Performance/Guides/Lazy_loading#images_iframes_video_audio).
This is in contrast to {{domxref("Document/DOMContentLoaded_event", "DOMContentLoaded")}}, which is fired as soon as the page DOM has been loaded, without waiting for resources to finish loading.

This event is not cancelable and does not bubble.
Expand Down
19 changes: 19 additions & 0 deletions files/en-us/web/html/reference/elements/audio/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ This element's attributes include the [global attributes](/en-US/docs/Web/HTML/R
> However, this can be useful when creating media elements whose source will be set at a later time, under user control.
> See our [autoplay guide](/en-US/docs/Web/Media/Guides/Autoplay) for additional information about how to properly use autoplay.

> [!NOTE]
> Audio with the [`loading="lazy"`](#loading) attribute set will not start downloading and autoplaying until the element is near or within the viewport.

- `controls`
- : If this attribute is present, the browser will offer controls to allow the user to control audio playback, including volume, seeking, and pause/resume playback.

Expand All @@ -65,6 +68,22 @@ This element's attributes include the [global attributes](/en-US/docs/Web/HTML/R

In Safari, you can use [`x-webkit-airplay="deny"`](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/AirPlayGuide/OptingInorOutofAirPlay/OptingInorOutofAirPlay.html) as a fallback.

- `loading`
- : Indicates how the browser should load the audio:
- `eager`
- : Loads the audio immediately, regardless of whether or not the audio is currently within the visible viewport (this is the default value).
- `lazy`
- : Defers loading the audio until it reaches a calculated distance from the viewport, as defined by the browser.

Lazy loading avoids the network and storage bandwidth required to handle the audio until it's reasonably certain that it will be needed. This improves the performance in most typical use cases.

Lazy-loaded audio located in the visual viewport may not yet be downloaded when the Window {{domxref("Window.load_event", "load")}} event is fired. This is because the event is fired based on eager-loaded audio only — lazy-loaded audio is not considered even if it is located within the visual viewport upon initial page load.

Loading is only deferred when JavaScript is enabled. This is an anti-tracking measure, because if a user agent supported lazy loading when scripting is disabled, it would still be possible for a site to track a user's approximate scroll position throughout a session, by strategically placing audio in a page's markup such that a server can track how many audio are requested and when.

> [!NOTE]
> The `loading="lazy"` attribute also impacts the [`autoplay`](#autoplay) attribute as described in that section of this page.

- `loop`
- : A Boolean attribute: if specified, the audio player will automatically seek back to the start upon reaching the end of the audio.
- `muted`
Expand Down
Loading
Loading