
Zero JavaScript Image Deferral with the Native HTML loading Attribute
For years, deferring offscreen images required either scroll event listeners or IntersectionObserver scripts coupled with data-src attributes. With the native HTML loading attribute standardized and shipping across Chromium-based browsers and Firefox in early 2020, browsers can now defer below-the-fold <img> and <iframe> elements automatically without a single line of JavaScript.
To prevent Cumulative Layout Shift (CLS) as deferred images load into view, always pair loading="lazy" with explicit width and height attributes so the browser can reserve the exact aspect-ratio box ahead of time. Meanwhile, keep loading="eager" (or omit the attribute) on above-the-fold hero images so your Largest Contentful Paint (LCP) is never delayed.
Example
<!-- Above the fold hero image: load immediately -->
<img
src="/img/hero-banner.webp"
alt="Featured mountain landscape"
width="1200"
height="630"
loading="eager"
/>
<!-- Below the fold gallery image: defer until near viewport -->
<img
src="/img/gallery-item-01.webp"
alt="Architectural detail of glass facade"
width="667"
height="518"
loading="lazy"
/>
Input : Long article page containing 20 high-resolution photographs
Output : Initial page load fetches only above-the-fold assets while reserving layout space for offscreen images.
Implementation
<article class="post-content">
<header class="post-hero">
<!-- Never lazy-load the primary hero image -->
<img
class="responsive-img"
src="/img/posts/featured-cover.webp"
alt="Clean Markup editorial workspace"
width="800"
height="500"
loading="eager"
/>
</header>
<section class="article-gallery">
<figure class="gallery-card">
<img
class="responsive-img"
src="/img/posts/diagram-architecture.webp"
alt="Browser rendering pipeline diagram"
width="667"
height="518"
loading="lazy"
/>
<figcaption>Figure 1: Native lazy loading defers network requests until scroll proximity.</figcaption>
</figure>
<figure class="gallery-card">
<img
class="responsive-img"
src="/img/posts/waterfall-benchmark.webp"
alt="Network waterfall comparison chart"
width="667"
height="518"
loading="lazy"
/>
<figcaption>Figure 2: Reduced initial payload size on 3G connections.</figcaption>
</figure>
</section>
</article>
/* Allow the browser to compute intrinsic aspect ratio from width and height attributes */
.responsive-img {
display: block;
max-width: 100%;
height: auto;
border-radius: 6px;
background-color: #f1f5f9;
}
.article-gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
margin-top: 32px;
}
// Optional feature detection fallback for older browsers that require a lightweight polyfill
if ("loading" in HTMLImageElement.prototype) {
console.log("Native lazy loading is supported by this browser.");
} else {
// Dynamically load a fallback IntersectionObserver script only when needed
const script = document.createElement("script");
script.src = "/js/lazysizes.min.js";
document.body.appendChild(script);
}
Main Point: Always apply loading="lazy" along with explicit width and height dimensions to below-the-fold images, and never lazy-load your primary above-the-fold hero image.
Credits
Photo by illahe