Testing

Loading Lazy: Browser Support, Syntax, Limitations

loading=lazy works in Chrome 77+, Edge 79+, Firefox 121+, Safari 16.4+, Opera 64+, and Samsung Internet 12+. Learn the syntax and the known issues.

Author

Prince Dewani

May 1, 2026

The HTML loading attribute is a WHATWG hint on img and iframe elements that tells the browser when to fetch the resource, and loading=lazy defers the fetch until the element nears the viewport. It works by default in Chrome 77+, Edge 79+, Firefox 121+, Safari 16.4+ on macOS and iOS, Opera 64+, and Samsung Internet 12+, while Internet Explorer never supported it.

This guide covers what loading=lazy is, the browsers that support it, the syntax, how it works, how to feature-detect it, and the known issues.

What is the loading=lazy attribute?

loading=lazy is a value of the HTML loading attribute, defined in the WHATWG HTML Standard for img and iframe elements. It tells the browser to defer the network fetch until the element is within a calculated distance of the viewport. The other accepted value is eager, which is the browser default.

Which browsers does loading=lazy support?

Every modern desktop and mobile browser supports loading=lazy by default on img elements, and recent versions add the same support for iframes. Internet Explorer and the legacy Android Browser never shipped support.

Loading browser compatibility data...

loading=lazy compatibility in Chrome

Chrome supports loading=lazy by default from Chrome 77 on Windows, macOS, Linux, ChromeOS, and Android, for both img and iframe elements. Chrome 75 to 76 had the attribute behind the chrome://flags/#enable-lazy-image-loading flag and was disabled by default. Chrome 4 to 74 did not support the attribute at all and ignored it as an unknown HTML hint.

loading=lazy compatibility in Edge

Microsoft Edge supports loading=lazy by default from Edge 79 on Windows, macOS, and Linux, on the Chromium engine. Legacy EdgeHTML 12 to 18 did not support the attribute, since the parser predated the WHATWG addition. Chromium-based Edge inherits the same Chrome behavior on every release going forward.

loading=lazy compatibility in Firefox

Firefox supports loading=lazy on img elements from Firefox 75 on Windows, macOS, Linux, and Android. Firefox added iframe support from Firefox 121, so cross-browser iframe lazy loading needs Firefox 121 or later. Firefox 2 to 74 did not support the attribute, and the older Gecko parser ignored it without warning.

loading=lazy compatibility in Safari

Safari supports loading=lazy by default from Safari 16.4 on macOS Ventura and from Safari 16.4 on iOS 16.4 and iPadOS 16.4. Safari 15.5 to 16.3 had partial support that lazy-loaded images only after a scroll event, which made the attribute unreliable on long pages and slow networks. Safari 3.2 to 15.4 did not support the attribute.

loading=lazy compatibility in Opera

Opera supports loading=lazy by default from Opera 64 on Windows, macOS, and Linux. Opera 62 to 63 had the attribute behind the same Chromium experimental flag and was disabled by default. Opera Mobile supports loading=lazy from Opera Mobile 80 on Android, and earlier Opera Mobile builds ignored the attribute.

loading=lazy compatibility in Samsung Internet

Samsung Internet supports loading=lazy by default from Samsung Internet 12 on Galaxy phones and tablets. The browser shares the underlying Chromium engine with Chrome on Android, so it picks up viewport-threshold tweaks the same way Chrome does. Samsung Internet 4 to 11.1 did not support the attribute on the older Chromium base.

loading=lazy compatibility in Android Browser

Chrome for Android supports loading=lazy from Chrome 77, and the modern Android WebView inherits the same Chromium behavior. The legacy Android Browser on KitKat and earlier did not support the attribute and never received a backport. Apps that embed a WebView pick up the feature once the device updates the system WebView component.

loading=lazy compatibility in Internet Explorer

Internet Explorer 6 through 11 do not support loading=lazy. The Trident parser drops the attribute as unknown markup and fetches every img and iframe immediately during the initial parse. Microsoft has retired Internet Explorer, so users on Windows who need lazy loading should switch to Microsoft Edge 79 or later.

Note

Note: loading=lazy behaves differently across Safari, Firefox iframe support, and older Android WebView builds. Test it on real browsers and OS with TestMu AI. Try TestMu AI free!

What is the syntax of the loading attribute?

The loading attribute lives directly on img and iframe elements and accepts two keyword values. It pairs cleanly with the width, height, and decoding attributes that browsers use to reserve layout space and pick a decode strategy.

  • loading=lazy: Defers the fetch of the img or iframe until the element is within a calculated distance of the viewport. Use it on every below-the-fold image, every embedded YouTube or map iframe, and any decorative image that the user may never scroll to.
  • loading=eager: Loads the resource immediately during the initial parse. This is the default when no loading attribute is set, and the right value for the LCP image, the logo, and any image that the user sees in the first viewport.
  • Pair with width and height: Always set width and height (or an aspect-ratio) on a lazy-loaded img so the browser reserves layout space before the fetch. A missing dimension causes Cumulative Layout Shift when the deferred image arrives.
  • Combine with fetchpriority: The fetchpriority attribute (high, low, auto) tunes the priority of the fetch independently of loading. fetchpriority=high on a lazy image lifts the request once it does fire, which is useful inside a carousel that the user is about to swipe.
  • Works on iframe too: Add loading=lazy to a third-party embed (a YouTube player, a Google Map, a Twitter widget) so the browser does not pull megabytes of script and stylesheets before the user scrolls to the embed.

How does loading=lazy work?

When the browser parses an img or iframe with loading=lazy, it skips the immediate network fetch and queues the element for an internal IntersectionObserver. The fetch fires only once the element comes within the viewport threshold, at which point the browser drops the attribute hint and treats the request as a normal eager load.

  • Viewport thresholds in Chrome and Edge: Chrome and Chromium-based Edge use a 1250-pixel threshold on fast 4G connections and a 2500-pixel threshold on 3G or slower, measured from the current scroll position to the element. Firefox and Safari use slightly smaller thresholds tuned to their own paint pipelines.
  • Layout reservation: The browser still parses the img or iframe and reserves the box from the width and height attributes (or the CSS aspect-ratio). The placeholder lives in the layout from the first paint, and the bytes only arrive when the user scrolls close.
  • Triggers the same load event: Once the fetch fires and the resource decodes, the img or iframe dispatches the standard load event the same way an eager image does. JavaScript that listens on load keeps working without changes.
  • Independent of IntersectionObserver: The browser-level threshold runs in the engine, not on the page. You do not need to wire up your own IntersectionObserver, and the engine threshold runs even when JavaScript is disabled.
...

How do you check if a browser supports loading=lazy?

Run the property check loading in HTMLImageElement.prototype in JavaScript. The expression returns true on every browser that supports loading=lazy on img, and false on browsers that need a polyfill.

// Detect native loading="lazy" support before you upgrade your image markup
if ('loading' in HTMLImageElement.prototype) {
  document.querySelectorAll('img[data-lazy-src]').forEach((img) => {
    img.loading = 'lazy';
    img.src = img.dataset.lazySrc;
  });
  console.log('Native loading="lazy" is supported on this browser');
} else {
  // Fall back to an IntersectionObserver-based polyfill on older browsers
  import('./lazy-load-polyfill.js').then(({ observe }) => observe('img[data-lazy-src]'));
  console.log('Native lazy loading is not supported, polyfill loaded');
}

For iframe support, swap HTMLImageElement for HTMLIFrameElement. The two properties report independently because Firefox shipped the img attribute long before the iframe attribute, and a feature-detect that only checks the img path will report a false positive on Firefox 75 to 120 for iframes.

What are the known issues with loading=lazy?

loading=lazy ships in every modern browser, but the way each engine measures the viewport threshold, handles hidden carousels, and treats the LCP image still trips up production sites.

  • Hero image marked lazy delays LCP: Marking the Largest Contentful Paint image as loading=lazy pushes the fetch past the initial parse, which can move the LCP by 1 to 3 seconds on a slow connection. Always leave the hero image as loading=eager (or omit the attribute) and apply lazy only to images below the first viewport.
  • Carousels load all slides at once in Chrome: Chrome 121 and later prefetch images inside a horizontal-scrolling carousel even when loading=lazy is set, because the engine treats the off-screen slides as imminent. Set fetchpriority=low on the non-visible slides if you want the browser to keep them deferred.
  • Missing width and height causes layout shift: A lazy image with no dimensions paints at zero height until the bytes arrive, then jumps to its real size. Always set width and height on the img tag, or set an aspect-ratio in CSS, so the placeholder reserves space from the first paint.
  • display:none images do not always defer: Some browsers fetch a hidden img immediately because the element has no viewport position to measure against. Move the image into the DOM only when you need it, or use the IntersectionObserver API for elements you toggle through display.
  • Background images are not covered: The loading attribute applies to img and iframe only. CSS background-image, picture sources, and video posters fetch eagerly regardless of any loading hint on a parent. Use content-visibility:auto or an IntersectionObserver to defer those.
  • In my experience, the failure that bites teams the most is shipping loading=lazy on the LCP image to satisfy a Lighthouse "lazy load offscreen images" suggestion, when Lighthouse only flags the off-screen ones. The fix is to scope the attribute to images below the fold and to keep loading=eager on the hero, the logo, and any image inside the first viewport.
...

Citations

All loading=lazy version numbers and platform notes in this guide come from these primary sources:

Author

Prince Dewani is a Community Contributor at TestMu AI, where he manages content strategies around software testing, QA, and test automation. He is certified in Selenium, Cypress, Playwright, Appium, Automation Testing, and KaneAI. Prince has also presented academic research at the international conference PBCON-01. He further specializes in on-page SEO, bridging marketing with core testing technologies. On LinkedIn, he is followed by 4,300+ QA engineers, developers, DevOps experts, tech leaders, and AI-focused practitioners in the global testing community.

Open in ChatGPT Icon

Open in ChatGPT

Open in Claude Icon

Open in Claude

Open in Perplexity Icon

Open in Perplexity

Open in Grok Icon

Open in Grok

Open in Gemini AI Icon

Open in Gemini AI

Copied to Clipboard!
...

3000+ Browsers. One Platform.

See exactly how your site performs everywhere.

Try it free
...

Write Tests in Plain English with KaneAI

Create, debug, and evolve tests using natural language.

Try for free

Frequently asked questions

Did you find this page helpful?

More Related Hubs

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests