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! 😎