# loading-attribute-polyfill: lazy loading that degrades gracefully

> This is a dependency-free JavaScript polyfill for the native loading="lazy" attribute on images and iframes, built so that browsers without support fall back to loading everything. It needs a noscript wrapper around each image and it has not shipped a new release since March 2023, although the repository was pushed to on 2026-10-10.

**mfranzke/loading-attribute-polyfill** — Fast and lightweight dependency-free vanilla JavaScript polyfill for native lazy loading / the awesome loading='lazy'-attribute.

- Repository: https://github.com/mfranzke/loading-attribute-polyfill
- Website: https://mfranzke.github.io/loading-attribute-polyfill/demo/
- Stars: 622 · Forks: 45
- Language: JavaScript
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/mfranzke-loading-attribute-polyfill

## What the polyfill stands in for

The native behaviour being replaced is simple: elements are loaded right before they enter the viewport. Browsers that implement the `loading="lazy"` attribute on `img` and `iframe` elements do that natively, and this package provides the same behaviour for the ones that do not, in plain JavaScript with no dependencies. Two design concepts are stated for the project, dependency-free and graceful degradation, and both are visible in the result. The package is described as lightweight, it follows the standard attribute so the markup is valid either way, and it is stated to be compatible down to Microsoft Internet Explorer 9, which tells you how little modern syntax it relies on. The licence is MIT and the project is made in Germany, with the contributors credited separately in the documentation.

## The noscript wrapper is the actual mechanism

Adding the attribute to an image is not enough, and the reason is the fallback path. The polyfill only takes over an image if the browser cannot handle the attribute itself, and it distinguishes the two cases by looking for a wrapper. Every `img` or `iframe` you want lazy loaded, and the complementary `source` tags when you use `picture`, has to be wrapped in a `noscript` element carrying the class `loading-lazy`. A browser with native support ignores that wrapper and loads the image normally; a browser without support shows the noscript content, which is the image itself, so the page still works. The documentation also insists on `width` and `height` attributes on image tags, because the browser can work out the aspect ratio from those two values even when CSS overrides them, which is what stops the page from reflowing as images arrive. The last piece of advice is to avoid lazy loading images that are in the first visible viewport.

## Three script builds and one stylesheet

Integration means including one JavaScript file and the CSS file, and the package ships several builds so you can pick the one that fits your setup:
```html
<link rel="stylesheet" href="dist/loading-attribute-polyfill.css" />
<script src="dist/loading-attribute-polyfill.umd.js" async></script>
```
The UMD build is the one that works with a plain script tag, and it is loaded asynchronously in the example. If you bundle, the module build is imported instead:
```js
import loadingAttributePolyfill from "node_modules/loading-attribute-polyfill/dist/loading-attribute-polyfill.module.js";
```
The manifest points at different files for different consumers, with the source file, a browser build, an esmodule build, a module build and the UMD main build each mapped separately, so the right variant is picked depending on how the package is consumed. The project can also be installed from a package registry, and the documentation notes that it can be loaded asynchronously, which matters because a polyfill is the wrong thing to make the rest of the page wait for.

## Why crawlers and non-JavaScript readers are the point

The SEO argument is the one that decides whether you reach for this package at all. The documentation is explicit that the image and iframe contents are not hidden from crawlers that are not capable of scrolling, which is the usual failure of naive lazy loading scripts: a crawler that never scrolls sees an empty page, and the content effectively disappears from the index. The noscript wrapper arrangement is what prevents that, because the fallback content is present in the markup for anything that does not execute the polyfill. There is a second group of consumers the design protects, which is readers with JavaScript disabled or blocked by an extension, who get the plain images rather than a broken layout. The documentation also mentions that the polyfill can be reinitialised for pages whose HTML is generated by JavaScript, which is the case the plain attribute does not cover on its own.

## The service worker alternative and its three limits

The project points to a second solution, published separately, whose main architectural decision is to use a Service Worker to intercept the network requests for image and iframe content. The project is candid that this changes the trade-offs, and lists three constraints: Service Workers only run over HTTPS for security reasons, a Service Worker has to be registered on the first page visit, and it only works on same domain network requests. The first of those is no longer much of an obstacle, since HTTPS is the de facto standard, but the other two are the ones that decide the choice. The polyfill you would otherwise use behaves as a progressive enhancement that provides the expected functionality for non-supporting browsers, on subsequent page requests and revisits, and for same origin image and iframe requests. If your content is on a different domain, or you cannot wait for a registration on the first visit, the Service Worker route is the wrong one.

## A small package with a long gap since the last release

The maintenance picture deserves a straight answer. The tagged releases are v2.1.1, published on 2023-03-12 as a maintenance release, v2.1.0 on 2022-05-16, and v2.0.2 on 2022-04-10. The last push to the repository was on 2026-10-10, so work is still landing in the tree, but the published version has not moved since 2023.

What the repository does show is a well equipped small project: a `src/` directory with the polyfill source, a `dist/` directory with the built variants, a `demo/` folder with an example page, and `webdriverio-tests/` for cross browser testing driven by WebdriverIO. The tooling is a mix of microbundle for the build, XO and Prettier for style, html-validate for the demo markup, husky with commitlint for conventional commits, and renovate for dependency updates. There is a MIGRATION.md, which is the file to read if you are moving from an older major version, and the package still carries a `bower.json` for the long tail of Bower users.

## Conclusion

The polyfill fits a site that has committed to the loading="lazy" attribute and wants the same behaviour in browsers that never implemented it, without pulling in a framework or a dependency, and the noscript wrapper approach keeps the content visible to crawlers and to readers without JavaScript. It is the wrong choice for a new project that can rely on native support, since the extra markup costs you and the package has not published a release since v2.1.1 on 2023-03-12, and it is the wrong choice if you need the service worker architecture, because that lives in a separate project with its own constraints. Before adopting it, check the width and height attributes on every image you wrap, since the polyfill relies on them for the aspect ratio, and read MIGRATION.md if you are coming from an older version, because the wrapper markup and the script build names have both changed over time.

## FAQ

### How do I install the loading="lazy" polyfill?

Install it from a package registry with npm install loading-attribute-polyfill, or the older Bower route with bower install loading-attribute-polyfill. You can then include one of the built JavaScript files from the dist folder together with the CSS file.

### What do I have to change in my HTML to use the polyfill?

Every img or iframe you want lazy loaded has to be wrapped in a noscript element with the class loading-lazy, and for picture elements you use the complementary source tags. You should also add width and height attributes to image tags so the browser can determine the aspect ratio.

### Does the polyfill hide images from search engine crawlers?

No. The design point is that image and iframe contents are not hidden from crawlers that are not capable of scrolling, because the fallback content stays in the markup for anything that does not run the polyfill.

### What is the Service Worker based alternative to this polyfill?

It is a separate project that intercepts image and iframe network requests with a Service Worker. The documented limits are that Service Workers only run over HTTPS, must be registered on the first page visit, and only work on same domain requests.

### Is the loading-attribute-polyfill still maintained?

The last published release was v2.1.1 on 2023-03-12, and the last push to the repository was on 2026-10-10. The repository still carries cross browser WebdriverIO tests, a microbundle build, linting, and dependency update tooling.

## Sources

- [License: MIT](https://github.com/mfranzke/loading-attribute-polyfill/blob/main/LICENSE)
- [mfranzke/loading-attribute-polyfill on GitHub](https://github.com/mfranzke/loading-attribute-polyfill)
- [Project website](https://mfranzke.github.io/loading-attribute-polyfill/demo/)
- [README](https://github.com/mfranzke/loading-attribute-polyfill/blob/main/README.md)
- [Releases](https://github.com/mfranzke/loading-attribute-polyfill/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mfranzke-loading-attribute-polyfill
