I would appreciate some help with my lazy loading scripts. For reasons that escape me, images within the plugin Master Slider don't get lazy loaded.
My JavaScript searches for all images with a data-src attribute. If an image has the attribute, it exchanges it with a regular src attribute and the image loads. If no data-src is present, the image is left alone.
Prior to this, I intended for a PHP script to get all images and exchange src with data-src, so the images can't load with the page.
It works on everything but the image slider. It's implemented via the plugin Master Slider.
I think the problem has to be within the PHP, since the slider does load - just not lazily. All src attributes work, which means JavaScript left the slider alone.
Does anyone have an idea why this is?
PHP:
add_filter( 'the_content', 'my_lazyload_content_images' );
add_filter( 'widget_text', 'my_lazyload_content_images' );
add_filter( 'wp_get_attachment_image_attributes', 'my_lazyload_attachments', 10, 2 );
// Replace the image attributes in Post/Page Content
function my_lazyload_content_images( $content ) {
//-- Change src/srcset to data attributes.
$content = preg_replace( '/(<img.+)(src)/Ui', '$1data-$2', $content );
$content = preg_replace( '/(<img.+)(srcset)/Ui', '$1data-$2', $content );
//-- Add .lazy-load class to each image that already has a class.
$content = preg_replace('/<img(.*?)class=\"(.*?)\"(.*?)>/i', '<img$1class="$2 lazy-load"$3>', $content);
//-- Add .lazy-load class to each image that doesn't already have a class.
$content = preg_replace('/<img((.(?!class=))*)\/?>/i', '<img class="lazy-load"$1>', $content);
return $content;
}
// Replace the image attributes in Post Listing, Related Posts, etc.
function my_lazyload_attachments( $atts, $attachment ) {
$atts['data-src'] = $atts['src'];
unset( $atts['src'] );
if( isset( $atts['srcset'] ) ) {
$atts['data-srcset'] = $atts['srcset'];
unset( $atts['srcset'] );
}
return $atts;
}
JavaScript:
let lazyImgs = document.querySelectorAll("img[data-src]");
function lazyLoad(lazyImgs) {
const imgOptions = {
threshold: 0.25,
rootMargin: "0%",
};
const imgObserver = new IntersectionObserver((entries, imgObserver) => {
entries.forEach((entry) => {
if (entry.intersectionRatio > 0) {
// get currently intersecting picture element and its children (source, img)
let lazyImage = entry.target;
// check if the element really has the attribute data-src, which we're using for lazy loading
// if it doesn't leave the image alone
if (lazyImage.hasAttribute("data-src")) {
// exchange the src
lazyImage.src = lazyImage.dataset.src;
// also exchange the src, if the image has one
if (lazyImage.srcset) {
lazyImage.srcset = lazyImage.dataset.srcset;
}
} else {
return false;
}
lazyImage.classList.add('is-loaded');
// end observation of image once it's loaded :)
imgObserver.unobserve(lazyImage);
} // end is intersecting
});
}, imgOptions);
// loop through all images and observe every single one
lazyImgs.forEach((lazyImg) => {
imgObserver.observe(lazyImg);
});
} // end lazyLoad();
lazyLoad(lazyImgs);
And the CSS:
.lazy-load {
transition: opacity .15s;
opacity: 0;
}
.lazy-load.is-loaded {
opacity: 1;
}