Lazy Loading Images in WordPress

In this blog, I am going tell you the quickest and easiest way to create lazy loading without using any libraries.We are just going to use simpleCSS and JavaScript

Lazy loading demo

The Concept

We first add the lightweight image URL in the src and srset attributes, and the actual image URL and actual srcset into data-src and data-srcset respectively.
On initial page load, on window resize, scroll and change in orientation we call the lazyload() with debounce.
The lazy load function loops through each image on the page and checks if its in the viewport .
If it is in the viewport, takes the original image URLs from the data-src and data-srcset attributes and replace the lightweight image with the original one, so we get a blur effect.
We will also add a image container with off-white background and a proper set height( using padding in % ) so it shows when while the images are being loaded.

How can we achieve lazy-load?

PHP

We can register the custom thumbnails like lazy-12x8 for the post and then regenerate thumbnails using Regenerate thumbnail plugin .

functions.phpfunction lazy_load_setup() {  add_image_size( 'lazy-12x8', 12, 8, array( 'center', 'center' ) );}add_action( 'after_setup_theme', 'lazy_load_setup' );

Now inside our page e.g. index.php

<?php
/* Start the Loop */
while
( have_posts() ) : the_post(); $img_src_array = wp_get_attachment_image_src( get_post_thumbnail_id( get_the_ID() ), 'full' );
$img_src_lightweight_array = wp_get_attachment_image_src( get_post_thumbnail_id( get_the_ID() ), 'lazy-12x8' );
$img_srcset = wp_get_attachment_image_srcset( get_post_thumbnail_id( get_the_ID() ) ); ?>
<div class="post-container">
<h3><?php the_title(); ?></h3>
<?php if ( has_post_thumbnail() ) {
?>
<div class="lazy-image">
<div class="thumbnail">
<?php
echo
wp_get_attachment_image(
get_post_thumbnail_id( get_the_ID() ),
'full',
false,
[
'data-src' => esc_url( $img_src_array[0] ),
'data-srcset' => $img_srcset,
'src' => esc_url( $img_src_lightweight_array[0] ),
'alt' => esc_html( get_the_title() ),
'srcset' => esc_url( $img_src_lightweight_array[0] ),
]
)
?>
</div>
</div>
<?php
}
?>
</div>
<?phpendwhile;
<?php

Styles

.lazy-image {
height: 0;
padding-bottom: 62.25%;
position: relative;
}.lazy-image .thumbnail {
margin: 0 auto;
overflow: hidden;
position: absolute;
background-color: #f5f5f5;
height: 100%;
width: 100%;
top: 0;
left: 0;
}.lazy-image .thumbnail img {
min-width: auto;
min-height: auto;
width: 100%;
height: 100%;
-o-object-fit: cover;
object-fit: cover;
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}

JavaScript

Lets write a debounce function in so that lazyload function does not get called repeatedly when the scrollevent is fired.

main.js/*
* Calls the given function after the given interval.
*
* @param {Object} func Function name.
* @param {number} wait Time in milliseconds.
*
* @return {Function} Debounced function.
*/
export const
debounce = ( func, wait ) => { let timeout; /**
* Debounce function.
*/
return function
() { const context = this,
args = arguments; /**
* Later function.
*/
const
later = function() {
timeout = null;
func.apply( context, args );
}; clearTimeout( timeout ); timeout = setTimeout( later, wait );
};};

Lets add lazyload feature and also use the above debounce function created.

// When the content is loaded.
document.addEventListener('DOMContentLoaded', function() { // Get all the images on the page that have 'data-src' attribute.
let
lazyloadImages = document.querySelectorAll('[data-src]'); /**
* Lazy load function.
*
* Loops through each img on the page and checks if its in the viewport.
* If it is in the viewport, takes the original image size from the 'data-src', and 'data-srcset' attributes and
* replaces the lightweight image
*/
function
lazyload () { // Loop through each image on the page.
lazyloadImages.forEach(function( img ) { // Get the top position of each image.
const
imgTop = img.getBoundingClientRect().top; // Check id image in Viewport ( If the image top position is less than window's inner height.
if
( imgTop < window.innerHeight ) { // Get the original image size from the 'data-src' attributed and replace the lightweight image with the original one.
const
dataSrc = img.getAttribute( 'data-src' );
img.setAttribute( 'src', dataSrc ); // Get the original image size from the 'data-srcset' attributed and replace the lightweight image with the original one.
const
dataSrcSet = img.getAttribute( 'data-srcset' ); if ( dataSrcSet ) {
img.setAttribute( 'srcset', dataSrcSet );
}
}
}); // If there are no images on the page, remove the events.
if
( 0 === lazyloadImages.length ) {
document.removeEventListener("scroll", lazyload);
window.removeEventListener("resize", lazyload);
window.removeEventListener("orientationChange", lazyload);
}
} /**
* Add events on 'scroll', 'resize' and 'orientationchange'
* Also use debounce to avoid multiple functions calls within the same time interval.
*/
document.addEventListener("scroll", debounce( lazyload, 300 ) );
window.addEventListener("resize", debounce( lazyload, 300 ));
window.addEventListener("orientationChange", debounce( lazyload, 300 )); // Call the lazyload() first time the window loads.
lazyload();});

And that’s it. When all you have to do is just used the same structure with where-ever you want the lazy load. You can also implement the similar approach in any non WordPress site which just uses HTML and CSS with JavaScript.

If you like my work, please star my git repo to support me and please follow me on : 🙏

Twitter — @imranhsayed

Github — imranhsayed

Lazy Load

Leave a Reply