Intersection Observer Lazy Loader
A component built to utilize intersection observers to implement lazy loading. It is extendable to allow for custom lazy loading of any component.
Settings
There are four settings the component will accept:
- queryString: this is the query string used get all elements from the DOM that will be lazy loaded.
- successCallback: this is the callback for when an element enters/exits the viewport.
- errorCallback: callback for if the browser doesn't support intersection observers
- margins: the space around the edge viewport the script will allow the component to be in before executing the callback. Defaults to no space.
The Callbacks
The success callback will take three parameters:
- (Node) entry: this is the element that entered the viewport
- (Object) observer: the observer that is watching the entry and invoked the callback. Can be used to unbind the entry after it is loaded in.
- (boolean) isIntersecting: whether the entry is in or out of the viewport.
The error callback takes one parameter:
- (Node) entry: this is the element that should be loaded in.
The error callback will default to the success callback if none is provided - and will just be fired on the DOMContentLoaded
event for each entry that it would have otherwise been bound to.
Using The Component
First, drop the component into your project and import it into wherever you will be performing your lazy loading.
Next, to add lazy loading you'll use one function: setupObservers
.
Default Use Case
The default use case is for adding lazy loading to image sources, source sets, and images as backgrounds via CSS. This is done with the following attributes:
- io-img-src: will be set to the image tag's
src
attribute on the image coming into the viewport - io-img-srcset: will be set to the image tags 'srcset' attribute on the image coming into the viewport
- io-bg-src: will be set as the element's
background-image
style. - io-bg-srcset: will be used to create media queries for setting the elements
background-image
style (example to follow). Requires the element to also have a unique data-io-id
attribute (for scoping styles correctly).
Here's an example of setting up lazy loading for an image, and also for adding background images to a div. First, we need the markup and then perform the JS setup:
<!-- HTML / Liquid -->
<img io-img-src="www.image.com/my-image.png" io-img-srcset="www.image.com/my-image.png 400w, www.image.com/my-image-big.png 800w" />
<div data-io-id="{{- section.id -}}" io-bg-srcset="www.image.com/my-image.png 0px, www.image.com/my-image-big.png 800px, www.image.com/my-image-extra-big.png 1200px"></div>
/** JS */
import LazyLoad from '@bva/iolazyload';
document.addEventListener('DOMContentLoaded', () => {
LazyLoad.setupObservers();
});
Adding Custom Callbacks
It's possible to add custom callbacks for any element:
<!-- HTML -->
<article data-lazy-article>
...
</article>
/** JS */
import LazyLoad from '@bva/iolazyload';
const displayArticle = (entry) => {
entry.classList.add('loaded');
};
const successCallback = (entry, observer, isIntersecting) => {
if (isIntersecting) {
displayArticle(entry);
observer.unobserve(entry);
}
};
document.addEventListener('DOMContentLoaded', () => {
LazyLoad.setupObservers({
queryString: '[data-lazy-article]',
callback: successCallback,
errorCallback: displayArticle,
margins: '10% 10% 10% 10%'
});
});
Notice we use the observer object, and once the article is loaded then unobserve it so as not to try and keep loading it in everytime it scrolls into view.
Custom Events
The component adds a custom event that is dispatched in the default success callback after an element has had its src
or background style updated when it comes into view.
The event is ioSourceSet
and is bound to the document. The events details.target
property refers to the element that was loaded into view.
Here's an example where we add the class loaded
to an element once the default callback has loaded the element:
document.addEventListener('ioSourceSet', (event) => {
const elementLoaded = event.detail.target;
elementLoaded.classList.add('loaded');
});