Skip to content

Instantly share code, notes, and snippets.

@neefrehman
Last active December 14, 2018 15:43
Show Gist options
  • Save neefrehman/c079c1b5a6abbb3588b0162cce3980b3 to your computer and use it in GitHub Desktop.
Save neefrehman/c079c1b5a6abbb3588b0162cce3980b3 to your computer and use it in GitHub Desktop.
lil' lazy loader

The littlest lazy loader

A teeny lazy loader to make your site more performant, by only loading images as they get near the viewport. 33 lines of code, 863 bytes of data (460 minified), vanilla javascript only.

Features

  • Written in Vanilla JS, no other dependencies
  • Will take data-src attribute and load in an src attribute for images
  • If data-src is not on an img, lzy.js will fallback to applying background-image to element's style
  • Will remove the data-src attribute once loading is done
  • Can pass in an offset value which controls how far the images are from the viewport before being loaded. By default this is 200px
  • Uses the intersectionObserver API, with a polyfill method for unsupported browsers at the bottom of this Readme

Usage

To use lzy.js include the script in your html file

<script src="lzy.js> </script>

Setup

Ensure all the elements you want lazily-loaded have a data-src attribute, with the path to the image you want to use.

<img data-src="path_to_image.jpg">

This will resolve to

<img src="path_to_image.jpg">

Or for any non img element it will resove to

<div style="background-image: url("path_to_image.jpg);"> </div>

Trigger

To trigger it, add the following function at the bottom of lzy.js, or in script that's loaded afterwards if you want more control.

lzy();

Options

To customise the offset value, call it like below. This scenario will load images as they get 500px from the viewport.

lzy({
  offset: 500
});

Polyfill for Intersection Observer

lzy.js uses the intersectionObserver API, which currently doesn't have an amazing amount of browser support. pollyfill.io to the rescue! To add support, add the following script to your html file, before lazy.js

<script> if (!window.IntersectionObserver) document.write('<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"> <\/script>'); </script>
const lzy = ({ offset } = {}) => {
const images = document.querySelectorAll("[data-src]");
const config = {
rootMargin: offset ? `${offset}px ${offset}px` : "200px 200px",
threshold: 0.01
};
function loadImage(imageEl) {
const imageSource = imageEl.getAttribute("data-src");
if (imageEl.tagName === "IMG") {
imageEl.setAttribute("src", imageSource);
} else {
imageEl.style.backgroundImage = `url(${imageSource})`;
}
imageEl.removeAttribute("data-src");
}
const observer = new IntersectionObserver(onIntersection, config);
images.forEach(function(image) {
observer.observe(image);
});
function onIntersection(entries) {
entries.forEach(function(entry) {
if (entry.intersectionRatio > 0) {
observer.unobserve(entry.target);
loadImage(entry.target);
}
});
}
};
const lzy=({offset:a}={})=>{function b(g){const h=g.getAttribute("data-src");"IMG"===g.tagName?g.setAttribute("src",h):g.style.backgroundImage=`url(${h})`,g.removeAttribute("data-src")}const d=document.querySelectorAll("[data-src]"),e={rootMargin:a?`${a}px ${a}px`:"200px 200px",threshold:0.01},f=new IntersectionObserver(function(g){g.forEach(function(h){0<h.intersectionRatio&&(f.unobserve(h.target),b(h.target))})},e);d.forEach(function(g){f.observe(g)})};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment