Skip to content

Commit aa62f1b

Browse files
feat: fallback if loading="lazy" unsupported
1 parent 95c432a commit aa62f1b

File tree

3 files changed

+62
-13
lines changed

3 files changed

+62
-13
lines changed

README.md

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ Keep in mind that manually loading images might negatively affect the perceived
185185

186186
## API
187187

188-
### `lazyLoadImages(selectors: string)`
188+
### `lazyLoadImages(selectors)`
189189

190190
The main method of the library. It works as follows:
191191

@@ -194,15 +194,62 @@ The main method of the library. It works as follows:
194194
3. If the image has a blurry placeholder and is already in the viewport or the visitor is a crawler, it immediately loads the full-quality image.
195195
4. If the image is not yet in the viewport, an event listener is added to load the full-quality image when it enters the viewport.
196196

197+
**Type Declaration**
198+
199+
```ts
200+
function lazyLoadImages(
201+
/**
202+
* A CSS selector or a list of CSS selectors to match images to lazy load.
203+
*
204+
* @default 'img[loading="lazy"]'
205+
*/
206+
selectors?: string,
207+
/**
208+
* A callback function to run when an image is loaded.
209+
*/
210+
onLoaded?: (image: HTMLImageElement) => void
211+
): void
212+
```
213+
197214
#### `selectors`
198215

199216
Defaults to `img[loading="lazy"]`. Allowed types are a valid CSS selector string.
200217

201-
### `autoSizes(selectors: string)`
218+
#### `onLoaded`
219+
220+
An optional callback function to run when an image is loaded. It accepts an `HTMLImageElement` as a parameter.
221+
222+
### `autoSizes(selectors)`
223+
224+
**Type Declaration**
225+
226+
```ts
227+
function autoSizes(
228+
/**
229+
* A CSS selector or a list of CSS selectors to calculate the `sizes` attribute for.
230+
*
231+
* @default 'img[data-sizes="auto"], source[data-sizes="auto"]'
232+
*/
233+
selectors?: string
234+
): void
235+
```
236+
237+
#### `selectors`
202238

203239
Defaults to `img[data-sizes="auto"], source[data-sizes="auto"]`. Allowed types are a valid CSS selector string.
204240

205-
### `loadImage(element: HTMLImageElement)`
241+
### `loadImage(element)`
242+
243+
**Type Declaration**
244+
245+
```ts
246+
function loadImage(
247+
image: HTMLImageElement,
248+
onLoaded?: (image: HTMLImageElement) => void
249+
): void
250+
```
251+
252+
#### `element`
206253

207254
An instance of `HTMLImageElement` representing the image you want to load manually.
208255

src/index.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export const isLazyLoadingSupported = 'loading' in HTMLImageElement.prototype
12
export const isCrawler = !('onscroll' in window) || /(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent)
23

34
export function lazyLoadImages(
@@ -10,7 +11,7 @@ export function lazyLoadImages(
1011
/**
1112
* A callback function to run when an image is loaded.
1213
*/
13-
onLoad?: (image: HTMLImageElement) => void,
14+
onLoaded?: (image: HTMLImageElement) => void,
1415
) {
1516
for (const image of [...document.querySelectorAll<HTMLImageElement>(selectors)]) {
1617
// Calculate the image's `sizes` attribute if `data-sizes="auto"` is set
@@ -20,22 +21,22 @@ export function lazyLoadImages(
2021
if (!image.dataset.srcset)
2122
continue
2223

23-
if (isCrawler) {
24-
// Let the crawler load the image
24+
// Use the same logic as for crawlers when native lazy-loading is not supported
25+
if (isCrawler || !isLazyLoadingSupported) {
2526
updatePictureSources(image)
2627
updateImageSrcset(image)
27-
onLoad?.(image)
28+
onLoaded?.(image)
2829
continue
2930
}
3031

3132
if (image.complete && image.naturalWidth > 0) {
3233
// Load the image if it's already in the viewport
33-
loadImage(image, onLoad)
34+
loadImage(image, onLoaded)
3435
continue
3536
}
3637

3738
// Otherwise, load the image when it enters the viewport
38-
image.addEventListener('load', () => loadImage(image, onLoad), { once: true })
39+
image.addEventListener('load', () => loadImage(image, onLoaded), { once: true })
3940
}
4041
}
4142

@@ -53,7 +54,7 @@ export function autoSizes(
5354

5455
export function loadImage(
5556
image: HTMLImageElement,
56-
onLoad?: (image: HTMLImageElement) => void,
57+
onLoaded?: (image: HTMLImageElement) => void,
5758
) {
5859
const imageLoader = new Image()
5960
imageLoader.srcset = image.dataset.srcset!
@@ -62,12 +63,11 @@ export function loadImage(
6263
imageLoader.addEventListener('load', () => {
6364
updatePictureSources(image)
6465
updateImageSrcset(image)
65-
onLoad?.(image)
66+
onLoaded?.(image)
6667
})
6768
}
6869

6970
export default Object.freeze({
70-
isCrawler,
7171
lazyLoadImages,
7272
autoSizes,
7373
loadImage,

vite.config.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { resolve } from 'node:path'
22
import { defineConfig } from 'vite'
33

4+
const currentDir = new URL('.', import.meta.url).pathname
5+
46
export default defineConfig({
57
build: {
68
// minify: false,
79
// target: 'esnext',
810
lib: {
9-
entry: resolve(__dirname, 'src/index.ts'),
11+
entry: resolve(currentDir, 'src/index.ts'),
1012
name: 'unlazy',
1113
formats: ['es', 'umd', 'iife'],
1214
},

0 commit comments

Comments
 (0)