How to Implement Lazy Loading with a Noscript Fallback for Maximum Compatibility

Wrap a standard <img> tag inside a <noscript> block next to your lazy-loaded images to guarantee content visibility when JavaScript is disabled, while using the loading="lazy" attribute and a lightweight polyfill to handle modern and legacy browsers.

The Front-End-Checklist repository establishes that robust image delivery requires redundant strategies to handle varying browser capabilities and user settings. According to the guidelines found in README.md, implementing lazy loading with noscript fallback ensures your images load efficiently for most users while remaining accessible to those on legacy browsers or with JavaScript disabled.

The Three-Layer Compatibility Strategy

The checklist outlines a defense-in-depth approach spanning three distinct layers.

Native lazy loading handles modern browsers (Chrome 76+, Firefox 75+, Safari 16+) that support the loading="lazy" attribute, deferring offscreen images until the user scrolls near them.

Polyfill support targets older browsers—specifically Safari ≤14 and Internet Explorer—that lack native lazy-loading capabilities. As noted in lines 500–505 of README.md, the recommended loading-attribute-polyfill adds native-like behavior without custom JavaScript.

Noscript fallback ensures content accessibility when JavaScript is completely disabled. Lines 520–530 of README.md explicitly require wrapping a standard <img> element inside <noscript> tags to display the image immediately in no-JavaScript environments.

Step 1: Implement Native Lazy Loading

Start by adding the loading="lazy" attribute to your image tags, using src for a lightweight placeholder and data-src for the high-resolution asset:

<img
  src="placeholder.jpg"
  data-src="hero-large.jpg"
  loading="lazy"
  alt="A stunning mountain landscape"
  class="lazyload" />

This defers the network request for hero-large.jpg until the element approaches the viewport, significantly improving initial page load time and bandwidth usage.

Step 2: Include the Polyfill for Legacy Browsers

To support browsers that do not recognize the loading attribute, include the loading-attribute-polyfill referenced in the Front-End-Checklist. Load it with the defer attribute to avoid render-blocking:

<script src="https://unpkg.com/loading-attribute-polyfill@2.0.0/dist/loading-attribute-polyfill.min.js"
        defer></script>

The polyfill automatically detects elements with loading="lazy" or the lazyload class, swapping the data-src value into src when the element enters the viewport. This provides graceful degradation without requiring custom intersection observer code.

Step 3: Add the Noscript Fallback

Finally, implement the noscript fallback pattern as specified in lines 520–530 of README.md. Place a standard <img> tag inside <noscript> tags immediately after your lazy-loaded image:

<noscript>
  <img src="hero-large.jpg" alt="A stunning mountain landscape">
</noscript>

Browsers with JavaScript enabled ignore this block entirely, while those with JavaScript disabled render the full-resolution image immediately. The duplicate markup ensures zero loss of content accessibility.

Complete Working Example

Combine all three layers into a robust implementation that handles modern browsers, legacy engines, and disabled JavaScript:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Lazy-Loaded Gallery with Noscript Fallback</title>
  <style>
    .gallery img { max-width: 100%; height: auto; display: block; margin-bottom: 1rem; }
  </style>
</head>
<body>
  <section class="gallery">
    <!-- Lazy-loaded image for JS-enabled browsers -->
    <img src="tiny-placeholder.jpg"
         data-src="sunset-large.jpg"
         loading="lazy"
         alt="Sunset over the ocean"
         class="lazyload">
    
    <!-- Fallback for no-JS environments -->
    <noscript>
      <img src="sunset-large.jpg" alt="Sunset over the ocean">
    </noscript>
    
    <!-- Second image -->
    <img src="tiny-placeholder.jpg"
         data-src="forest-large.jpg"
         loading="lazy"
         alt="Forest trail"
         class="lazyload">
    
    <noscript>
      <img src="forest-large.jpg" alt="Forest trail">
    </noscript>
  </section>

  <!-- Polyfill for browsers without native lazy loading support -->
  <script src="https://unpkg.com/loading-attribute-polyfill@2.0.0/dist/loading-attribute-polyfill.min.js"
          defer></script>
</body>
</html>

This implementation covers all three scenarios: modern browsers use native lazy loading, older browsers rely on the polyfill's intersection observer logic, and JavaScript-disabled environments fall back to the noscript content.

Summary

  • Use loading="lazy" on image elements to enable native lazy loading in modern browsers.
  • Include the loading-attribute-polyfill (as referenced in README.md lines 500–505) to extend support to Safari ≤14 and Internet Explorer.
  • Always provide a <noscript> fallback containing a standard <img> tag, as required by lines 520–530 of the Front-End-Checklist, to ensure images remain visible when JavaScript is disabled.
  • Reserve layout space with tiny placeholder images in the src attribute to prevent cumulative layout shift (CLS) while the lazy-loaded content downloads.

Frequently Asked Questions

Do I need both the polyfill and the noscript fallback?

Yes. The polyfill handles browsers that support JavaScript but lack native lazy-loading APIs, such as Safari 14 and older. The noscript fallback handles users who have disabled JavaScript entirely. Together, they provide complete coverage across the browser capability spectrum as recommended by the Front-End-Checklist.

Will duplicate image requests occur in modern browsers?

No. Modern browsers that support loading="lazy" and execute JavaScript will ignore the contents of <noscript> tags, preventing duplicate downloads. The polyfill only activates in browsers where the native attribute is unrecognized, ensuring only one version of the image loads per environment.

What size should the placeholder image be?

Use a tiny, low-resolution version of the final image or a transparent 1×1 pixel GIF in the src attribute. This reserves the layout space to prevent layout shift while the high-resolution image loads via data-src. The Front-End-Checklist emphasizes maintaining layout stability during the lazy-loading process.

Does this pattern work for responsive images with srcset?

Yes. Apply the same pattern to <picture> elements or srcset attributes by placing the full responsive markup inside the <noscript> block. For the lazy-loaded version, move the srcset value to data-srcset (which the polyfill supports) while keeping a tiny placeholder in src.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →