A tutorial for loading an image as soon as it enters the viewport, using the Intersect plugin of the AlpineJS framework.
🌍 The French version of this publication : AlpineJS : Implémenter le lazy loading des images avec le plugin Intersect
Introduction
AlpineJS is a lightweight JavaScript framework that makes your HTML dynamic.
Among the plugins provided by AlpineJS is Intersect, a wrapper for JavaScript's Intersection Observer API. This plugin reacts as soon as an element enters the browser's viewport.
The viewport is the area of the window in which web content can be viewed, i.e. the visible part of the page at the level of the scroll bar.
In this tutorial, we'll look at the Lazy loading technique for loading an image as soon as it enters the browser's viewport. This improves the performance of a web page by reducing its loading weight, as images, which can be heavy, are loaded only when they are about to be seen in the user interface.
At the time of writing, I'm using version 3 of AlpineJS and the Intersect plugin.
Installing AlpineJS and Intersect
First, let's create a basic HTML structure into which we'll integrate AlpineJS and the Intersect plugin via CDN. Next, we'll add the logic of lazy loading of images in JavaScript. Long Lorem Ipsum text is inserted in the <p>
paragraph to fill the page, with a margin (margin-bottom
) of 1000px
below. This allows the image to be moved out of the viewport and loaded only when it becomes visible.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lazy image loading with AlpineJS and Intersect</title>
</head>
<body>
<h1>Welcome to my website</h1>
<!-- Long content to scroll page -->
<p style="margin-bottom: 1000px;" >Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat ...</p>
<!-- The image to load -->
<img src="https://loremflickr.com/320/240" alt="Image Lazyload" />
</body>
</html>
Install via CDN
We can include AlpineJS and the Intersect plugin in a <script>
tag before closing the </body>
tag. Be sure to add the plugin before the main AlpineJS file.
<!-- Importing Intersect via CDN -->
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/intersect@3.x.x/dist/cdn.min.js"></script>
<!-- Importing AlpineJs via CDN -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
Install via NPM
To install AlpineJS and the Intersect plugin, use the following commands:
npm install alpinejs
npm install @alpinejs/intersect
Once installed, we can initialize them in our bundle.
import Alpine from 'alpinejs';
import intersect from '@alpinejs/intersect';
Alpine.plugin(intersect);
Alpine.start();
Implementing Lazy Loading
Once the libraries have been imported, we will proceed as follows to add the logic of lazy loading of images with AlpineJS and Intersect:
1. Define <body>
as an AlpineJS component by assigning x-data
:
<body x-data>
...
</body>
2. For images, use a lightweight image (GIF or SVG) in the src
attribute to indicate loading, while storing the URL of the actual image in data-src
, then add the x-intersect
directive to trigger the load_image
function as soon as the image enters the viewport:
<img x-intersect="load_image" data-src="https://loremflickr.com/320/240" src="./images/loader.gif" alt="Image Lazyload" />
To load the image only the first time it enters the viewport and not subsequent times, we add the .once
modifier to x-intersect
:
<img x-intersect.once="load_image" ... />
3. Define the load_image
function to retrieve the image path from data-src
and update the src
attribute:
function load_image() {
// Retrieves the <img> element concerned
const image = this.$el;
// Retrieves image path from "data-src"
const image_src = image.getAttribute("data-src");
// Replaces the "src" attribute with the actual image
image.src = image_src;
}
Here is the complete source code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lazy image loading with AlpineJS and Intersect</title>
</head>
<body x-data >
<h1>Welcome to my website</h1>
<!-- Long content to scroll page -->
<p style="margin-bottom: 1000px;" >Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat ...</p>
<!-- The image to load -->
<img x-intersect.once="load_image" data-src="https://loremflickr.com/320/240" src="./images/loader.gif" alt="Image Lazyload" />
<!-- Importing Intersect via CDN -->
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/intersect@3.x.x/dist/cdn.min.js"></script>
<!-- Importing AlpineJs via CDN -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script>
function load_image() {
// Retrieves the <img> element concerned
const image = this.$el;
// Retrieves image path from "data-src"
const image_src = image.getAttribute("data-src");
// Replaces the "src" attribute with the actual image
image.src = image_src;
}
</script>
</body>
</html>
I believe this tip will improve your web pages by making them perform better thanks to image lazyloading.
Take care! 😎