Ask me anything
Ithy Logo
Sign in to save

Comprehensive WordPress Lazy Load Plugin Code

All-inclusive plugin code for lazy loading images everywhere

wordpress website screens lazy loading images

Highlights

  • Full functionality: Implements lazy loading for all image types (WebP, PNG, SVG, etc.) across single posts, pages, homepages, feature images, content images, and sidebar images.
  • User-configurable settings: Dashboard options provide selections for preloaded images (SVG, PNG, WebP) and more.
  • Structured file organization: Comprehensive code with clear file paths, functions, and integration with WordPress Settings API for an intuitive admin dashboard.

Overview

This guide offers a complete WordPress plugin solution that implements lazy loading for various image formats across your website sections. The plugin will ensure images on single posts, pages, the homepage, feature images, in-content images, and sidebar images load only when they are needed, significantly enhancing page speed and performance. Additionally, the plugin includes a settings page in the dashboard to allow users to select a preload image style (e.g., SVG, PNG, WebP) before lazy loading the actual content.

Plugin Structure and File Organization

The plugin is organized into multiple files and directories under a main directory called lazy-load-images inside your wp-content/plugins/ folder. Below is the file structure:

File/Folder Description Path
Main Plugin File Entry point for the plugin initialization wp-content/plugins/lazy-load-images/lazy-load-images.php
Settings File Dashboard settings page for preload image selection wp-content/plugins/lazy-load-images/settings.php
Functions Contains plugin functionality for processing images wp-content/plugins/lazy-load-images/includes/functions.php
Helpers Helper functions to output dynamic preload URLs wp-content/plugins/lazy-load-images/includes/helpers.php
JavaScript Lazy loading script for handling image scrolling events wp-content/plugins/lazy-load-images/assets/js/lazy-load-images.js
CSS Styling for lazy loading classes wp-content/plugins/lazy-load-images/assets/css/lazy-load-images.css
Preload Images Default images used before actual loading wp-content/plugins/lazy-load-images/assets/images/

Complete Plugin Code

1. Main Plugin File - lazy-load-images.php

<?php
/*
Plugin Name: Lazy Load Images
Description: A powerful plugin to lazy load images across your WordPress site (single posts, pages, homepage, feature images, content images, and sidebar images) supporting multiple formats like WebP, PNG, SVG, etc.
Version: 1.0
Author: Your Name
*/

// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

// Define plugin directory path and URL
define( 'LLI_DIR', plugin_dir_path( __FILE__ ) );
define( 'LLI_URL', plugin_dir_url( __FILE__ ) );

// Include necessary files
require_once LLI_DIR . 'includes/functions.php';
require_once LLI_DIR . 'includes/helpers.php';
require_once LLI_DIR . 'settings.php';

// Enqueue plugin scripts and styles
function lli_enqueue_scripts() {
    wp_enqueue_script( 'lli-lazy-load', LLI_URL . 'assets/js/lazy-load-images.js', array('jquery'), '1.0', true );
    wp_enqueue_style( 'lli-styles', LLI_URL . 'assets/css/lazy-load-images.css' );
}
add_action( 'wp_enqueue_scripts', 'lli_enqueue_scripts' );

// Add settings menu in admin dashboard
function lli_add_admin_menu() {
    add_menu_page( 'Lazy Load Images Settings', 'Lazy Load Images', 'manage_options', 'lazy-load-images', 'lli_settings_page', 'dashicons-format-image', 81 );
}
add_action( 'admin_menu', 'lli_add_admin_menu' );
?>

2. Settings Page File - settings.php

<?php
// Settings page callback function
function lli_settings_page() {
    ?>
    <div class="wrap">
        <h1>Lazy Load Images Settings</h1>
        <form method="post" action="options.php">
            <?php
            settings_fields( 'lli_options_group' ); // Settings group name
            do_settings_sections( 'lazy-load-images' );
            ?>
            <table class="form-table">
                <tr valign="top">
                    <th scope="row">Preload Image</th>
                    <td>
                        <select name="lli_preload_image">
                            <option value="preload-svg.svg" <?php selected( get_option( 'lli_preload_image' ), 'preload-svg.svg' ); ?>>SVG</option>
                            <option value="preload-png.png" <?php selected( get_option( 'lli_preload_image' ), 'preload-png.png' ); ?>>PNG</option>
                            <option value="preload-webp.webp" <?php selected( get_option( 'lli_preload_image' ), 'preload-webp.webp' ); ?>>WebP</option>
                        </select>
                    </td>
                </tr>
            </table>
            <?php submit_button( 'Save Changes' ); ?>
        </form>
    </div>
    <?php
}

// Register settings
function lli_register_settings() {
    register_setting( 'lli_options_group', 'lli_preload_image' );
}
add_action( 'admin_init', 'lli_register_settings' );
?>

3. Functions File - includes/functions.php

<?php
// Function to lazy load all images within post content
function lli_lazy_load_images_content( $content ) {
    if( is_single() || is_page() ) {
        // Use DOMDocument to modify img tags
        $dom = new DOMDocument();
        libxml_use_internal_errors(true);
        $dom->loadHTML( $content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
        foreach( $dom->getElementsByTagName('img') as $img ) {
            $src = $img->getAttribute('src');
            $srcset = $img->getAttribute('srcset');
            $sizes = $img->getAttribute('sizes');
            $currentClass = $img->getAttribute('class');
            
            // Append custom lazy class and modify attributes
            $img->setAttribute( 'class', $currentClass . ' lli-lazyload' );
            $img->setAttribute( 'data-src', $src );
            if( !empty( $srcset ) ) {
                $img->setAttribute( 'data-srcset', $srcset );
            }
            if( !empty( $sizes ) ) {
                $img->setAttribute( 'data-sizes', $sizes );
            }
            // Optionally remove src attribute so browser will load preload image from CSS
            $img->removeAttribute( 'src' );
        }
        return $dom->saveHTML();
    }
    return $content;
}
add_filter( 'the_content', 'lli_lazy_load_images_content' );

// Function to lazy load post thumbnail (featured image)
function lli_lazy_load_post_thumbnail( $html ) {
    $dom = new DOMDocument();
    libxml_use_internal_errors(true);
    $dom->loadHTML( $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
    foreach( $dom->getElementsByTagName('img') as $img ) {
        $src = $img->getAttribute('src');
        $srcset = $img->getAttribute('srcset');
        $sizes = $img->getAttribute('sizes');
        $currentClass = $img->getAttribute('class');
        $img->setAttribute( 'class', $currentClass . ' lli-lazyload' );
        $img->setAttribute( 'data-src', $src );
        if( !empty( $srcset ) ) {
            $img->setAttribute( 'data-srcset', $srcset );
        }
        if( !empty( $sizes ) ) {
            $img->setAttribute( 'data-sizes', $sizes );
        }
        $img->removeAttribute( 'src' );
    }
    return $dom->saveHTML();
}
add_filter( 'post_thumbnail_html', 'lli_lazy_load_post_thumbnail' );

// Lazy loading images in widget areas (sidebar)
function lli_lazy_load_sidebar_images( $widget_text ) {
    $dom = new DOMDocument();
    libxml_use_internal_errors(true);
    $dom->loadHTML( $widget_text, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
    foreach( $dom->getElementsByTagName('img') as $img ) {
        $src = $img->getAttribute('src');
        $srcset = $img->getAttribute('srcset');
        $sizes = $img->getAttribute('sizes');
        $currentClass = $img->getAttribute('class');
        $img->setAttribute( 'class', $currentClass . ' lli-lazyload' );
        $img->setAttribute( 'data-src', $src );
        if( !empty( $srcset ) ) {
            $img->setAttribute( 'data-srcset', $srcset );
        }
        if( !empty( $sizes ) ) {
            $img->setAttribute( 'data-sizes', $sizes );
        }
        $img->removeAttribute( 'src' );
    }
    return $dom->saveHTML();
}
add_filter( 'widget_text', 'lli_lazy_load_sidebar_images' );
?>

4. Helpers File - includes/helpers.php

<?php
// Get preload image URL based on the settings option
function lli_get_preload_image_url() {
    $preload_image = get_option( 'lli_preload_image', 'preload-svg.svg' );
    return LLI_URL . 'assets/images/' . $preload_image;
}
?>

5. JavaScript File - assets/js/lazy-load-images.js

<?php
(function() {
    // Wait for the DOM content to be loaded
    document.addEventListener("DOMContentLoaded", function() {
        // Select all images marked for lazy loading
        var lazyImages = document.querySelectorAll('img.lli-lazyload');
        var options = {
            root: null,
            rootMargin: "0px",
            threshold: 0.1
        };

        // Intersection Observer callback function
        var loadImages = function(entries, observer) {
            entries.forEach(function(entry) {
                if (entry.isIntersecting) {
                    var img = entry.target;
                    if (img.dataset.src) {
                        img.src = img.dataset.src;
                    }
                    if (img.dataset.srcset) {
                        img.srcset = img.dataset.srcset;
                    }
                    if (img.dataset.sizes) {
                        img.sizes = img.dataset.sizes;
                    }
                    img.classList.remove("lli-lazyload");
                    observer.unobserve(img);
                }
            });
        };

        // Create observer if supported
        if ("IntersectionObserver" in window) {
            var observer = new IntersectionObserver(loadImages, options);
            lazyImages.forEach(function(img) {
                observer.observe(img);
            });
        } else {
            // Fallback: load all images immediately if IntersectionObserver not supported
            lazyImages.forEach(function(img) {
                if (img.dataset.src) {
                    img.src = img.dataset.src;
                }
                if (img.dataset.srcset) {
                    img.srcset = img.dataset.srcset;
                }
                if (img.dataset.sizes) {
                    img.sizes = img.dataset.sizes;
                }
                img.classList.remove("lli-lazyload");
            });
        }
    });
})();
?>

6. CSS File - assets/css/lazy-load-images.css

/* Define preload styling using background image */
.lli-lazyload {
    background: url(<?php echo lli_get_preload_image_url(); ?>) center center no-repeat;
    background-size: cover;
    opacity: 0.5;
    transition: opacity 0.5s ease-in-out;
}
.lli-lazyload[src] {
    opacity: 1;
}

Installation and Configuration

Step-by-step Process

1. Create a directory named lazy-load-images in wp-content/plugins/.
2. Inside this directory, create the following structure as described above:

  • lazy-load-images.php
  • settings.php
  • includes/functions.php
  • includes/helpers.php
  • assets/js/lazy-load-images.js
  • assets/css/lazy-load-images.css
  • assets/images/ (Include your preload images: preload-svg.svg, preload-png.png, preload-webp.webp)

3. Copy and paste the corresponding code snippets into the matching files ensuring that the file names and paths are as indicated.

4. Log in to your WordPress dashboard, navigate to Plugins → Add New and click on Upload Plugin if you wish to install via a ZIP archive, or simply activate the plugin if added manually via FTP.

5. Once activated, a new menu titled Lazy Load Images will appear in your admin sidebar. Go there to configure your settings including which preload image format to use.


Further Customizations and Testing

Testing in Different Scenarios

After installation, test the plugin by navigating through various sections of your website:

  • Check single post pages to confirm that both featured images and in-content images are loading via lazy loading.
  • Examine the homepage and other static pages to observe the lazy loading effect.
  • Inspect images within sidebars and widget areas.

Use browser developer tools to monitor network calls and confirm that images are loaded only when their container scrolls into view. Adjust the JavaScript Intersection Observer options if you need different threshold values or root margins for better performance.

Advanced Modifications

You may enhance this plugin further by adding:

  • Support for lazy loading background images on CSS elements.
  • A fallback mechanism, such as noscript tags, for older browsers.
  • Integration with caching plugins to optimize lazy loading performance.
  • Conditional loading based on device type or viewport size.

For advanced requirements, consider tweaking the plugin to dynamically replace placeholders with actual image sources upon viewport intersection.

References

Recommended Queries for Further Insight


Last updated March 23, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI