Skip to content

Commit da41a48

Browse files
fix: Chrome preloading images with placeholders too early
1 parent 8dbd470 commit da41a48

File tree

2 files changed

+22
-5
lines changed

2 files changed

+22
-5
lines changed

packages/core/src/lazyLoad.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export function lazyLoad<T extends HTMLImageElement>(
2727
if (updateSizesOnResize && onResizeCleanup)
2828
cleanupFns.add(onResizeCleanup)
2929

30+
const hasValidSrc = Boolean(image.src)
31+
3032
// Generate the blurry placeholder from a Blurhash or ThumbHash string if applicable
3133
if (
3234
// @ts-expect-error: Compile-time flag
@@ -43,15 +45,15 @@ export function lazyLoad<T extends HTMLImageElement>(
4345
image.src = placeholder
4446
}
4547

46-
// Bail if the image doesn't provide a `data-src` or `data-srcset` attribute
48+
// Bail if the image does not provide a `data-src` or `data-srcset` attribute
4749
if (!image.dataset.src && !image.dataset.srcset) {
4850
// @ts-expect-error: Compile-time flag
4951
if (typeof __UNLAZY_LOGGING__ === 'undefined' || __UNLAZY_LOGGING__)
5052
console.error('[unlazy] Missing `data-src` or `data-srcset` attribute', image)
5153
continue
5254
}
5355

54-
// Use the same logic as for crawlers when native lazy-loading is not supported
56+
// If native lazy loading is not supported, use the same logic as for crawlers
5557
if (isCrawler || !isLazyLoadingSupported) {
5658
updatePictureSources(image)
5759
updateImageSrcset(image)
@@ -64,8 +66,13 @@ export function lazyLoad<T extends HTMLImageElement>(
6466
if (!image.src)
6567
image.src = DEFAULT_IMAGE_PLACEHOLDER
6668

67-
// Load the image if it's already in the viewport
68-
if (image.complete && image.naturalWidth > 0) {
69+
// Load immediately if:
70+
// 1. Either the image has a valid `src` attribute and it is already loaded
71+
// 2. Or it is already in the viewport (even with placeholder)
72+
if (
73+
(hasValidSrc && image.complete && image.naturalWidth > 0)
74+
|| isPartiallyInViewport(image)
75+
) {
6976
loadImage(image, onImageLoad)
7077
continue
7178
}
@@ -260,3 +267,13 @@ function getOffsetWidth(element: HTMLElement | HTMLSourceElement) {
260267
? element.parentElement?.getElementsByTagName('img')[0]?.offsetWidth
261268
: element.offsetWidth
262269
}
270+
271+
function isPartiallyInViewport(element: HTMLElement) {
272+
const rect = element.getBoundingClientRect()
273+
return (
274+
rect.top < window.innerHeight
275+
&& rect.bottom >= 0
276+
&& rect.left < window.innerWidth
277+
&& rect.right >= 0
278+
)
279+
}

packages/core/src/utils/dataUri/png.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* @remarks
77
* This is optimized for speed and simplicity and does not optimize for size
8-
* at all. This doesn't do any compression (all values are stored uncompressed).
8+
* at all. This does not do any compression (all values are stored uncompressed).
99
*
1010
* @see https://github.com/evanw/thumbhash
1111
* @author Evan Wallace

0 commit comments

Comments
 (0)