<iframe> elements often consume more bandwidth than other types of
resources. In the case of
<iframe> elements, a fair amount of extra processing
time can be involved in loading and rendering the pages within them.
In the case of lazy loading images, deferring the loading of images that are outside of the initial viewport can be helpful in reducing bandwidth contention for more critical resources within the initial viewport. This can improve a page's Largest Contentful Paint (LCP) in some cases where network connections are poor, and that reallocated bandwidth can help LCP candidates load and paint faster.
<iframe> elements are concerned, a page's Interaction to Next Paint
(INP) can be improved during startup by lazy loading them. This is because an
<iframe> is a completely separate HTML document with its own subresources.
<iframe> elements can be run in a separate process, it's not uncommon
for them to share a process with other threads, which can create conditions
where pages become less responsive to user input.
Thus, deferring the loading of off-screen images and
<iframe> elements is a
technique worth pursuing, and requires fairly low effort for a reasonably good
return in terms of performance. This module covers explains to lazy load these
two types of elements for a faster and better user experience during the page's
critical startup period.
Lazy load images with the
loading attribute can be added to
<img> elements to tell browsers how
they should be loaded:
"eager"informs the browser that the image should be loaded immediately, even if it's outside the initial viewport. This is also the default value for the
"lazy"defers loading an image until it's within a set distance from the visible viewport. This distance varies by browser, but is often set to be large enough that the image loads by the time the user scrolls to it.
It's also worth noting that if you're using the
<picture> element, the
loading attribute should still be applied to its child
<img> element, not
<picture> element itself. This is because the
<picture> element is a
container that contains additional
<source> elements pointing to different
image candidates, and the candidate that the browser chooses is applied directly
to its child
Don't lazy load images that are in the initial viewport
You should only add
loading="lazy" attribute to
<img> elements that are
positioned outside the initial viewport. However, it can be complex to know the
precise position of an element relative within the viewport before the page is
rendered. Different viewport sizes, aspect ratios, and devices have to be
For example, a desktop viewport can be quite different from a viewport on a mobile phone as it renders more vertical space which may be able to fit images in the initial viewport that wouldn't appear in the initial viewport of a physically smaller device. Tablets used in portrait orientation also display a considerable amount of vertical space, perhaps even more than some desktop devices.
However, there are some cases in which it's fairly clear that you should avoid
loading="lazy". For example, you should definitely omit the
loading="lazy" attribute from
<img> elements in cases of hero images,
or other image use cases where
<img> elements are likely to appear above the
fold, or near the top of the layout on any device. This is even more important
for images that are likely to be LCP candidates.
Images that are lazy loaded need to wait for the browser to finish layout in
order to know if the image's final position is within the viewport. This means
that if an
<img> element in the visible viewport has a
attribute, it's only requested after all CSS is downloaded, parsed, and
applied to the page—as opposed to being fetched as soon as it is discovered by
the preload scanner in the raw markup.
loading attribute on the
<img> element is supported on all major
affects other aspects of page performance, such as INP.
Image lazy loading demo
<iframe> elements until they are visible in the viewport can save
significant data and improve the loading of critical resources that are required
for the top-level page to load. Additionally, because
<iframe> elements are
essentially entire HTML documents loaded within a top-level document, they can
affect a page's INP considerably if the tasks within those frames requires
significant processing time.
Third-party embeds are a common use case for
<iframe> elements. For example,
embedded video players or social media posts commonly use
and they often require a significant number of subresources which can also
result in bandwidth contention for the top-level page's resources. As an
example, lazy loading a YouTube video's embed saves more than 500 KiB during
the initial page load, while lazy loading the Facebook Like button plugin
Either way, whenever you have an
<iframe> below the fold on a page, you should
strongly consider lazy loading it if it's not critical to load it up front, as
doing so can significantly improve the user experience.
loading attribute for
loading attribute on
<iframe> elements is also supported in all major
browsers. The values for the
loading attribute and their behaviors are the
same as with
<img> elements that use the
"eager"is the default value. It informs the browser to load the
<iframe>element's HTML and its subresources immediately.
"lazy"defers loading the
<iframe>element's HTML and its subresources until it is within a predefined distance from the viewport.
Lazy loading iframes demo
Instead of loading an embed immediately during page load, you can load it on demand in response to a user interaction. This can be done by showing an image or another appropriate HTML element until the user interacts with it. Once the user interacts with the element, you can replace it with the third-party embed. This technique is known as a facade.
This is a prime opportunity to show a static image that is visually similar to
the video embed and save significant bandwidth in the process. Once the user
clicks on the image, it's then replaced by the actual
<iframe> embed, which
triggers the third-party
<iframe> element's HTML and its subresources to begin
In addition to improving initial page load, another key upside is that if the user never plays the video, the resources required to deliver it are never downloaded. This is a good pattern, as it ensures the user only downloads what they actually want to, without making possibly faulty assumptions about the user's needs.
With a facade on the other hand, it's possible to replace the third-party "Start Chat" button with a fake button. Once the user meaningfully interacts with it—such as holding a pointer over it for a reasonable period of time, or with a click—the actual, functional chat widget is slotted into place when the user needs it.
While it's certainly possible to build your own facades, there are open source
options available for more popular third parties, such as
for YouTube videos,
lite-vimeo-embed for Vimeo videos, and React Live Chat
Loader for chat widgets.
If you need to lazy load
images loaded by the CSS
background-image property, or other unsupported
lazysizes or yall.js, as lazy loading these types of resources is not a
In particular, autoplaying and looping
<video> elements without an audio track
are a much more efficient alternative than using animated GIFs, which can
often be several times larger than a video resource of equivalent visual
quality. Even so, these videos can still be significant in terms of bandwidth,
so lazy loading them is an additional optimization that can go a long way to
reducing wasted bandwidth.
Most of these libraries work using the Intersection Observer API—and
additionally the Mutation Observer API if a page's HTML changes after the
initial load—to recognize when an element enters the user's viewport. If the
replaces the non-standard attribute, (often
data-src or a similar attribute),
with the correct attribute, such as
<!-- The autoplay, loop, muted, and playsinline attributes are to ensure the video can autoplay without user intervention. --> <video class="lazy" autoplay loop muted playsinline width="320" height="480"> <source data-src="video.webm" type="video/webm"> <source data-src="video.mp4" type="video/mp4"> </video>
By default, yall.js observes all qualifying HTML elements with a class of
"lazy". Once yall.js is loaded and executed on the page, the video doesn't
load until the user scrolls it into the viewport. At that point, the
attributes on the
<video> element's child
<source> elements are swapped out
src attributes, which sends a request to download the video and
automatically begin playing it.
Test your knowledge
Which is the default value for the
loading attribute for
loadingattribute isn't supported, such as in the case of autoplaying videos intended to replace animated images, or to lazy load a
<video>element's poster image.
When is a facade a useful technique?
Up next: Prefetching and prerendering
Now that you have a handle on lazy loading images and
you're in a good position to ensure that pages can load more quickly while
respecting the needs of your users. However, there are cases in which
speculative loading of resources can be desirable. In the next module,
learn about prefetching and prerendering, and how these techniques—when used
carefully—can substantially speed up navigations to subsequent pages by loading
them ahead of time.