Skip to content

Instantly share code, notes, and snippets.

@optimalisatie
Last active December 25, 2022 09:04
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save optimalisatie/be5793eee869082fea2e1ab7ffd77ef2 to your computer and use it in GitHub Desktop.
Save optimalisatie/be5793eee869082fea2e1ab7ffd77ef2 to your computer and use it in GitHub Desktop.
Image lazy loading with instant visibility of in-view images on page load (MutationObserver)
// Performance tests such as Google Lighthouse often complain about below the fold images while lazy loading
// techniques may introduce a flash effect for images on bigger screens
// This snippet shows a solution to instantly display images as if loaded using src="" while maintaining
// the lazy loading benefit on smaller screens.
// Tip: a second and potentially better technique is to rewrite lazy loaded images to regular src="" images in a Service Worker.
// this snippet depends on in-view (5kb)
// @link https://github.com/camwiegert/in-view/
// tiny cross browser domready method
// @link https://gist.github.com/dciccale/4087856
var DOMReady = function(a,b,c){b=document,c='addEventListener';b[c]?b[c]('DOMContentLoaded',a):window.attachEvent('onload',a)}
// requestAnimationframe
var RAF = window.requestAnimationframe || setTimeout;
var lazyToken = 'data-lzy';
// display image
var lazyResolve = function(el) {
// already loaded
if (!el.hasAttribute(lazyToken)) {
return;
}
// verify if image is hidden by parent
if (el.offsetParent !== null) {
// remove lazy marker (to mark as completed)
el.removeAttribute(lazyToken);
// requestAnimationFrame to prevent layout trashing
RAF(function() {
el.setAttribute('src', el.getAttribute(lazyToken));
});
}
}
// setup lazy load method
DOMReady(function() {
inView('['+lazyToken+']').on('enter', lazyResolve);
});
// instantly load visible images on render
var mutationObserver = window.MutationObserver || window.WebKitMutationObserver,
observer;
if (mutationObserver) {
observer = new mutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
var node;
for (var i = 0; i < mutation.addedNodes.length; i++) {
node = mutation.addedNodes[i];
if (node.nodeName === 'IMG' && node.hasAttribute(lazyToken)) {
if (inView.is(node)) {
// start download
new Image().src = node.getAttribute(lazyToken);
// display image with requestAnimationFrame
lazyResolve(node);
}
}
}
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment