Adding Lazy Loading to images on your site is a great way to make your site faster and lighter.
With lazy loading you'll load images only when needed, which they may never actually be for most sites where the above the fold content tends to
attract most of the attention from the majority of users.
This is often done with jQuery and this add-on, which works fine, but requires a rather massive 90KB or so for jQuery and another 8.84KB for the add-on.
An alternate solution
Here is an alternate solution which does not depend on jQuery, and does lazy loading for your page in just 1.63KB, small enough to inline into your pages. Obviously it is not as feature rich in some respects as the jQuery alternative, but for most people it will more than suffice, and save quite a few bytes in the process.
var LazyLoad = {
elements: [],
threshold: 200,
onLoadStart: null,
onLoadComplete: null,
Init: LazyLoad_Init,
Update: LazyLoad_Update,
MakeOnLoadComplete: LazyLoad_MakeOnLoadComplete,
GetNow: function () { return new Date().getTime(); }
};
function LazyLoad_MakeOnLoadComplete(e, image, now) {
if (!this.onLoadComplete) { return null; }
return function () { LazyLoad.onLoadComplete(e, image, LazyLoad.GetNow() - now); }
}
function LazyLoad_Init() {
var nodes = document.querySelectorAll("*[lazyLoad]");
this.elements = [];
for (var i = 0; i < nodes.length; ++i) {
this.elements.push(nodes[i]);
}
this.Update();
}
function LazyLoad_Update() {
var sx = window.pageXOffset;
var sy = window.pageYOffset;
var t = this.threshold;
var vr = { top: -t, bottom: window.innerHeight + t, left: -t, right: window.innerWidth + t };
var now = this.GetNow();
for (var i = 0; i < this.elements.length; ++i) {
var e = this.elements[i];
var r = e.getBoundingClientRect();
if (!(r.left > vr.right || vr.left > r.right || r.top > vr.bottom || vr.top > r.bottom)) {
var url = e.getAttribute("lazyLoad");
var img = new Image();
img.src = url;
if (this.onLoadStart) { this.onLoadStart(e, img); }
img.onload = this.MakeOnLoadComplete(e, img, now);
if (e.tagName == "IMG") {
e.src = url;
} else {
e.style.backgroundImage = 'url(' + url + ')';
}
this.elements.splice(i, 1);
i -= 1;
}
}
}
window.addEventListener("DOMContentLoaded", function () { LazyLoad.Init() });
window.addEventListener("scroll", function () { LazyLoad.Update() });
window.addEventListener("resize", function () { LazyLoad.Update() });
How to use
To do lazy loading just add the above code to your page and then for "img" tags, use a "lazyLoad" attribute in place of "src". If you want to set a CSS background, use a "lazyLoad" attribute instead of "background-image". That is really all there is too it.
If you want, you can also add callback functions for setting a temporary image or style on an item when loading starts, and/or perform some manner of animation when the image is actually loaded, bellow you'll find an example which fades in the image/div when loading completes, if it took more than 20 ms to load the image. This threshold can be used to give an "immediate" feel when the image is loaded very rapidly (like from the browsers cache).
LazyLoad.onLoadStart = function (e) { e.style.opacity = 0; };
LazyLoad.onLoadComplete = function (e, image, time) { if (time > 20) { e.style.transition = 'opacity 0.5s'; var t = e.offsetTop; }; e.style.opacity = 1; }
You can also adjust the threshold for when loading should start, the default is 200 pixels in every direction.