├── .nvmrc ├── .husky ├── .gitignore ├── commit-msg └── pre-commit ├── .browserslistrc ├── .prettierignore ├── .prettierrc.json ├── .vscode └── extensions.json ├── commitlint.config.js ├── src ├── loading-attribute-polyfill.css └── loading-attribute-polyfill.js ├── .gitattributes ├── renovate.json ├── dist ├── loading-attribute-polyfill.css ├── loading-attribute-polyfill.modern.css ├── loading-attribute-polyfill.module.css ├── loading-attribute-polyfill.css.map ├── loading-attribute-polyfill.modern.css.map ├── loading-attribute-polyfill.module.css.map ├── loading-attribute-polyfill.js ├── loading-attribute-polyfill.modern.js ├── loading-attribute-polyfill.module.js ├── loading-attribute-polyfill.umd.js ├── loading-attribute-polyfill.js.map ├── loading-attribute-polyfill.umd.js.map ├── loading-attribute-polyfill.module.js.map └── loading-attribute-polyfill.modern.js.map ├── demo ├── img │ ├── img-src-loadingeager.250x150.guetzli.jpg │ ├── lazyimg-src-loadinglazy.250x150.guetzli.jpg │ ├── lazypicture-1x-loadinglazy.250x150.guetzli.jpg │ ├── lazypicture-2x-loadinglazy.500x300.guetzli.jpg │ ├── lazyimg-srcset1024w-loadinglazy.1024x614.guetzli.jpg │ ├── lazyimg-srcset320w-loadinglazy.320x192.guetzli.jpg │ ├── lazyimg-srcset640w-loadinglazy.640x384.guetzli.jpg │ ├── lazypicture-imgsrc-loadinglazy.250x150.guetzli.jpg │ ├── lazypicture-media1x-loadinglazy.250x150.guetzli.jpg │ └── lazypicture-media2x-loadinglazy.500x300.guetzli.jpg ├── index.js └── index.html ├── .xo-config.json ├── .htmlvalidate.json ├── .npmignore ├── .github ├── workflows │ ├── reuse-compliance-check.yml │ ├── pull-request.yml │ ├── linter.yml │ └── codeql-analysis.yml └── FUNDING.yml ├── .editorconfig ├── .npmrc ├── bower.json ├── LICENSE ├── MIGRATION.md ├── package.json ├── .gitignore ├── webdriverio-tests ├── basic.js └── wdio.conf-crossbrowsertesting.js ├── CODE-OF-CONDUCT.md ├── LICENSES └── Apache-2.0.txt ├── CHANGELOG.md └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 22 2 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 0.1%, IE >= 9 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | commitlint --edit "$1" 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | package-lock.json 3 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5" 3 | } 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pretty-quick --staged 2 | git update-index --again 3 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["editorconfig.editorconfig"] 3 | } 4 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] }; 2 | -------------------------------------------------------------------------------- /src/loading-attribute-polyfill.css: -------------------------------------------------------------------------------- 1 | img[data-lazy-src] { 2 | will-change: contents; 3 | } 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | ":preserveSemverRanges" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /dist/loading-attribute-polyfill.css: -------------------------------------------------------------------------------- 1 | img[data-lazy-src]{will-change:contents} 2 | /*# sourceMappingURL=loading-attribute-polyfill.css.map */ -------------------------------------------------------------------------------- /dist/loading-attribute-polyfill.modern.css: -------------------------------------------------------------------------------- 1 | img[data-lazy-src]{will-change:contents} 2 | /*# sourceMappingURL=loading-attribute-polyfill.modern.css.map */ -------------------------------------------------------------------------------- /dist/loading-attribute-polyfill.module.css: -------------------------------------------------------------------------------- 1 | img[data-lazy-src]{will-change:contents} 2 | /*# sourceMappingURL=loading-attribute-polyfill.module.css.map */ -------------------------------------------------------------------------------- /demo/img/img-src-loadingeager.250x150.guetzli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfranzke/loading-attribute-polyfill/HEAD/demo/img/img-src-loadingeager.250x150.guetzli.jpg -------------------------------------------------------------------------------- /demo/img/lazyimg-src-loadinglazy.250x150.guetzli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfranzke/loading-attribute-polyfill/HEAD/demo/img/lazyimg-src-loadinglazy.250x150.guetzli.jpg -------------------------------------------------------------------------------- /demo/img/lazypicture-1x-loadinglazy.250x150.guetzli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfranzke/loading-attribute-polyfill/HEAD/demo/img/lazypicture-1x-loadinglazy.250x150.guetzli.jpg -------------------------------------------------------------------------------- /demo/img/lazypicture-2x-loadinglazy.500x300.guetzli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfranzke/loading-attribute-polyfill/HEAD/demo/img/lazypicture-2x-loadinglazy.500x300.guetzli.jpg -------------------------------------------------------------------------------- /demo/img/lazyimg-srcset1024w-loadinglazy.1024x614.guetzli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfranzke/loading-attribute-polyfill/HEAD/demo/img/lazyimg-srcset1024w-loadinglazy.1024x614.guetzli.jpg -------------------------------------------------------------------------------- /demo/img/lazyimg-srcset320w-loadinglazy.320x192.guetzli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfranzke/loading-attribute-polyfill/HEAD/demo/img/lazyimg-srcset320w-loadinglazy.320x192.guetzli.jpg -------------------------------------------------------------------------------- /demo/img/lazyimg-srcset640w-loadinglazy.640x384.guetzli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfranzke/loading-attribute-polyfill/HEAD/demo/img/lazyimg-srcset640w-loadinglazy.640x384.guetzli.jpg -------------------------------------------------------------------------------- /demo/img/lazypicture-imgsrc-loadinglazy.250x150.guetzli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfranzke/loading-attribute-polyfill/HEAD/demo/img/lazypicture-imgsrc-loadinglazy.250x150.guetzli.jpg -------------------------------------------------------------------------------- /demo/img/lazypicture-media1x-loadinglazy.250x150.guetzli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfranzke/loading-attribute-polyfill/HEAD/demo/img/lazypicture-media1x-loadinglazy.250x150.guetzli.jpg -------------------------------------------------------------------------------- /demo/img/lazypicture-media2x-loadinglazy.500x300.guetzli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfranzke/loading-attribute-polyfill/HEAD/demo/img/lazypicture-media2x-loadinglazy.500x300.guetzli.jpg -------------------------------------------------------------------------------- /dist/loading-attribute-polyfill.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["loading-attribute-polyfill.css"],"names":[],"mappings":"AAAA,mBACC,oBACD","file":"loading-attribute-polyfill.css","sourcesContent":["img[data-lazy-src] {\n\twill-change: contents;\n}\n"]} -------------------------------------------------------------------------------- /.xo-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "envs": ["browser"], 3 | "prettier": true, 4 | "esnext": false, 5 | "rules": { 6 | "unicorn/prefer-node-remove": "off", 7 | "unicorn/no-array-for-each": "off", 8 | "unicorn/prefer-dom-node-remove": "off" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /dist/loading-attribute-polyfill.modern.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["loading-attribute-polyfill.css"],"names":[],"mappings":"AAAA,mBACC,oBACD","file":"loading-attribute-polyfill.modern.css","sourcesContent":["img[data-lazy-src] {\n\twill-change: contents;\n}\n"]} -------------------------------------------------------------------------------- /dist/loading-attribute-polyfill.module.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["loading-attribute-polyfill.css"],"names":[],"mappings":"AAAA,mBACC,oBACD","file":"loading-attribute-polyfill.module.css","sourcesContent":["img[data-lazy-src] {\n\twill-change: contents;\n}\n"]} -------------------------------------------------------------------------------- /.htmlvalidate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["html-validate:document", "html-validate:recommended"], 3 | 4 | "rules": { 5 | "void-style": ["warn", { "style": "selfclosing" }], 6 | "script-type": "off", 7 | "require-sri": ["error", { "target": "crossorigin" }] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | demo 2 | webdriverio-tests 3 | .gitignore 4 | .husky 5 | commitlint.config.js 6 | .github 7 | .gitattributes 8 | .prettierignore 9 | .htmlvalidate.json 10 | bower.json 11 | 12 | # # # Individual additions 13 | .browserslistrc 14 | .vscode 15 | renovate.json 16 | .nvmrc 17 | -------------------------------------------------------------------------------- /.github/workflows/reuse-compliance-check.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2025 DB Systel GmbH 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | name: REUSE Compliance Check 6 | 7 | # on: [push, pull_request] 8 | 9 | jobs: 10 | reuse-compliance-check: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | 16 | - name: REUSE Compliance Check 17 | uses: fsfe/reuse-action@v5 18 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | name: pull-request 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | name: Build & Test 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Check out the source code 14 | uses: actions/checkout@v4 15 | 16 | - name: Set up NodeJS 17 | uses: actions/setup-node@v4 18 | with: 19 | node-version-file: '.nvmrc' 20 | 21 | - name: Install dependencies 22 | run: npm ci 23 | 24 | - name: Run tests 25 | run: npm test 26 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # For more information about the properties used in 2 | # this file, please see the EditorConfig documentation: 3 | # https://editorconfig.org/ 4 | 5 | root = true 6 | 7 | [*] 8 | charset = utf-8 9 | end_of_line = lf 10 | indent_style = tab 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | 17 | [*.js] 18 | quote_type = single 19 | 20 | [package.json] 21 | # The indent size used in the `package.json` file cannot be changed 22 | # https://github.com/npm/npm/pull/3180#issuecomment-16336516 23 | indent_size = 2 24 | indent_style = space 25 | 26 | [{*.yaml,*.yml}] 27 | indent_style = space 28 | indent_size = 2 29 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: loading-attribute-polyfill # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | # If set to false, then ignore package-lock.json files when installing. This will also prevent writing package-lock.json if save is true. source: https://docs.npmjs.com/cli/v11/using-npm/config 2 | package-lock=true 3 | # If true, npm does not run scripts specified in package.json files. source: https://docs.npmjs.com/cli/v11/using-npm/config#ignore-scripts 4 | ignore-scripts=true 5 | # Dependencies saved to package.json will be configured with an exact version rather than using npm's default semver range operator. source: https://docs.npmjs.com/cli/v11/using-npm/config#save-exact 6 | save-exact=true 7 | # If set to true, then npm will stubbornly refuse to install (or even consider installing) any package that claims to not be compatible with the current Node.js version. source: https://docs.npmjs.com/cli/v11/using-npm/config#engine-strict 8 | engine-strict=true 9 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "loading-attribute-polyfill", 3 | "description": "Fast and lightweight dependency-free vanilla JavaScript polyfill for native lazy loading / the awesome loading='lazy'-attribute.", 4 | "version": "2.1.0", 5 | "homepage": "https://github.com/mfranzke/loading-attribute-polyfill", 6 | "authors": [ 7 | { 8 | "name": "Maximilian Franzke", 9 | "url": "https://www.mfranzke.net/", 10 | "email": "contact_mfr@nzke.net" 11 | } 12 | ], 13 | "keywords": [ 14 | "lazy loading", 15 | "native lazy loading", 16 | "img", 17 | "image", 18 | "iframe", 19 | "polyfill", 20 | "web development", 21 | "javascript", 22 | "html", 23 | "front-end" 24 | ], 25 | "licenses": [ 26 | { 27 | "type": "MIT", 28 | "url": "https://opensource.org/licenses/mit-license.php" 29 | } 30 | ], 31 | "ignore": [ 32 | "demo", 33 | "webdriverio-tests", 34 | ".gitignore", 35 | ".husky", 36 | "commitlint.config.js", 37 | ".github", 38 | ".gitattributes", 39 | ".prettierignore", 40 | ".htmlvalidate.json", 41 | ".browserslistrc", 42 | ".vscode", 43 | "renovate.json" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Maximilian Franzke 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /demo/index.js: -------------------------------------------------------------------------------- 1 | import loadingAttributePolyfill from '../dist/loading-attribute-polyfill.module.js'; 2 | 3 | // Test for dynamically inserted images 4 | const addImage = (event) => { 5 | const divElement = document.createElement('div'); 6 | const noscriptElement = document.createElement('noscript'); 7 | const imageElement = document.createElement('img'); 8 | 9 | noscriptElement.classList.add('loading-lazy'); 10 | 11 | imageElement.setAttribute('src', 'https://via.placeholder.com/250x150'); 12 | imageElement.setAttribute('loading', 'lazy'); 13 | imageElement.setAttribute('alt', '..'); 14 | imageElement.setAttribute('width', '250'); 15 | imageElement.setAttribute('height', '150'); 16 | 17 | noscriptElement.append(imageElement); 18 | 19 | divElement.append(noscriptElement); 20 | 21 | document.querySelector('main').insertAdjacentElement('beforeend', divElement); 22 | 23 | // Call for preparing the sample image element included the latest 24 | loadingAttributePolyfill.prepareElement( 25 | document.querySelector('main noscript.loading-lazy') 26 | ); 27 | 28 | event.preventDefault(); 29 | }; 30 | 31 | document.querySelector('button.add-image').addEventListener('click', addImage); 32 | -------------------------------------------------------------------------------- /MIGRATION.md: -------------------------------------------------------------------------------- 1 | # Migration guidelines 2 | 3 | ## 2.0.0-beta.1 migration guide 4 | 5 | We've switched from previously only providing the source and a minified version of the JS, to additionally provide the different relevant JavaScript formats especially regarding modules supported by [microbundle](https://npmjs.com/microbundle). Thatfor we even also changed the location of the generated files as well as pointed the relevant property entries within the `package.json` to those files. Please find all the relevant generated files in the `dist/` folder from now on. 6 | 7 | ## 2.0.0-beta.0 migration guide 8 | 9 | You'll need to wrap the `` tag instead of the included HTML tags with `