Skip to content

Commit

Permalink
fix: Chrome preloading images with placeholders too early
Browse files Browse the repository at this point in the history
  • Loading branch information
johannschopplich committed Nov 12, 2024
1 parent 8dbd470 commit da41a48
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 5 deletions.
25 changes: 21 additions & 4 deletions packages/core/src/lazyLoad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export function lazyLoad<T extends HTMLImageElement>(
if (updateSizesOnResize && onResizeCleanup)
cleanupFns.add(onResizeCleanup)

const hasValidSrc = Boolean(image.src)

// Generate the blurry placeholder from a Blurhash or ThumbHash string if applicable
if (
// @ts-expect-error: Compile-time flag
Expand All @@ -43,15 +45,15 @@ export function lazyLoad<T extends HTMLImageElement>(
image.src = placeholder
}

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

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

// Load the image if it's already in the viewport
if (image.complete && image.naturalWidth > 0) {
// Load immediately if:
// 1. Either the image has a valid `src` attribute and it is already loaded
// 2. Or it is already in the viewport (even with placeholder)
if (
(hasValidSrc && image.complete && image.naturalWidth > 0)
|| isPartiallyInViewport(image)
) {
loadImage(image, onImageLoad)
continue
}
Expand Down Expand Up @@ -260,3 +267,13 @@ function getOffsetWidth(element: HTMLElement | HTMLSourceElement) {
? element.parentElement?.getElementsByTagName('img')[0]?.offsetWidth
: element.offsetWidth
}

function isPartiallyInViewport(element: HTMLElement) {
const rect = element.getBoundingClientRect()
return (
rect.top < window.innerHeight
&& rect.bottom >= 0
&& rect.left < window.innerWidth
&& rect.right >= 0
)
}
2 changes: 1 addition & 1 deletion packages/core/src/utils/dataUri/png.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* @remarks
* This is optimized for speed and simplicity and does not optimize for size
* at all. This doesn't do any compression (all values are stored uncompressed).
* at all. This does not do any compression (all values are stored uncompressed).
*
* @see https://github.com/evanw/thumbhash
* @author Evan Wallace
Expand Down

0 comments on commit da41a48

Please sign in to comment.