How to Implement Efficient Image Lazy Loading with Vanilla JavaScript
This guide explains the concept of image lazy loading, how to detect when an image enters the viewport, and provides a complete vanilla‑JavaScript implementation with throttled scroll handling to improve page performance and reduce bandwidth usage.
Definition Image lazy loading, also called delayed loading, loads images only when they enter the viewport, reducing requests, saving bandwidth, speeding up page load, and lowering server load. It improves user experience by avoiding loading large amounts of data at once.
Implementation The challenge is to detect whether an image is needed. In browsers, an image is needed when it appears in the visible area. We check if the image’s bounding rectangle intersects the viewport; if so, we replace its placeholder source with the real URL (image dimensions should be set, e.g., via padding).
Determine if an image is in the viewport:
Viewport height
Distance from the top of the page to the image
Using these two values we can decide whether the image is visible.
var nodes = document.querySelectorAll('img[data-src]'),
elem = nodes[0],
rect = elem.getBoundingClientRect(),
vpHeight = document.documentElement.clientHeight;
if (rect.top < vpHeight && rect.bottom >= 0) {
console.log('show');
}After detecting visibility, retrieve the real image URL.
<img src="loading.gif" alt="">
...
<script>
var src = elem.dataset.src;
</script>Assign the real URL to the image.
var img = new Image();
img.onload = function () {
elem.src = img.src;
};
img.src = src;Full code
var scrollElement = document.querySelector('.page'),
viewH = document.documentElement.clientHeight;
function lazyload() {
var nodes = document.querySelectorAll('img[data-src]');
Array.prototype.forEach.call(nodes, function (item) {
if (item.dataset.src === '') return;
var rect = item.getBoundingClientRect();
if (rect.bottom >= 0 && rect.top < viewH) {
(function (item) {
var img = new Image();
img.onload = function () {
item.src = img.src;
};
img.src = item.dataset.src;
item.dataset.src = '';
})(item);
}
});
}
lazyload();
scrollElement.addEventListener('scroll', throttle(lazyload, 500, 1000));
function throttle(fun, delay, time) {
var timeout,
startTime = new Date();
return function () {
var context = this,
args = arguments,
curTime = new Date();
clearTimeout(timeout);
if (curTime - startTime >= time) {
fun.apply(context, args);
startTime = curTime;
} else {
timeout = setTimeout(fun, delay);
}
};
}Demo
For demonstration, the demo adds a 500 ms delay to img.onload. Click to view the original demo.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
JavaScript
Provides JavaScript enthusiasts with tutorials and experience sharing on web front‑end technologies, including JavaScript, Node.js, Deno, Vue.js, React, Angular, HTML5, CSS3, and more.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
