Skip to content

Bits of .NET

Daily micro-tips for C#, SQL, performance, and scalable backend engineering.

  • Asp.Net Core
  • C#
  • SQL
  • JavaScript
  • CSS
  • About
  • ErcanOPAK.com
  • No Access
  • Privacy Policy
Wordpress

WordPress Speed Hack: How Lazy Loading Images Cuts Page Load Time in Half

- 05.02.26 - ErcanOPAK

WordPress sites loading slowly due to images? Native lazy loading with modern techniques dramatically improves performance.

// Add to functions.php
function add_lazy_loading_attributes($content) {
    // Only run on frontend
    if (is_admin() || wp_is_json_request()) {
        return $content;
    }
    
    // Use DOMDocument for reliable parsing
    if (class_exists('DOMDocument')) {
        $dom = new DOMDocument();
        @$dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'));
        
        $images = $dom->getElementsByTagName('img');
        
        foreach ($images as $image) {
            // Skip if already has loading attribute
            if ($image->hasAttribute('loading')) {
                continue;
            }
            
            // Add loading='lazy' to all images
            $image->setAttribute('loading', 'lazy');
            
            // Add decoding='async' for better performance
            $image->setAttribute('decoding', 'async');
            
            // If image is above the fold (first 3 images), use eager
            static $image_count = 0;
            if ($image_count < 3) {
                $image->setAttribute('loading', 'eager');
                $image_count++;
            }
        }
        
        // Save the modified HTML
        $content = $dom->saveHTML();
    }
    
    return $content;
}
add_filter('the_content', 'add_lazy_loading_attributes', 99);
add_filter('post_thumbnail_html', 'add_lazy_loading_attributes', 99);
add_filter('get_avatar', 'add_lazy_loading_attributes', 99);
add_filter('woocommerce_product_get_image', 'add_lazy_loading_attributes', 99);

// Advanced: Native lazy loading with intersection observer fallback
function enqueue_lazy_loading_scripts() {
    // Only for browsers that don't support native lazy loading
    wp_add_inline_script('jquery', '
        document.addEventListener("DOMContentLoaded", function() {
            if ("loading" in HTMLImageElement.prototype) {
                // Browser supports native lazy loading
                console.log("Using native lazy loading");
            } else {
                // Fallback to intersection observer
                console.log("Using intersection observer fallback");
                
                const images = document.querySelectorAll("img[loading=\"lazy\"]");
                
                if ("IntersectionObserver" in window) {
                    const imageObserver = new IntersectionObserver((entries) => {
                        entries.forEach((entry) => {
                            if (entry.isIntersecting) {
                                const img = entry.target;
                                img.src = img.dataset.src;
                                if (img.dataset.srcset) {
                                    img.srcset = img.dataset.srcset;
                                }
                                imageObserver.unobserve(img);
                            }
                        });
                    });
                    
                    images.forEach((img) => {
                        // Store original src in data-src
                        img.dataset.src = img.src;
                        img.dataset.srcset = img.srcset || "";
                        img.src = "data:image/svg+xml,%3Csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1 1\"%3E%3C/svg%3E";
                        img.srcset = "";
                        imageObserver.observe(img);
                    });
                } else {
                    // Fallback for very old browsers
                    images.forEach((img) => {
                        img.src = img.dataset.src;
                        if (img.dataset.srcset) {
                            img.srcset = img.dataset.srcset;
                        }
                    });
                }
            }
        });
    ');
}
add_action('wp_enqueue_scripts', 'enqueue_lazy_loading_scripts');

Related posts:

WordPress Admin Loads Plugins You Don’t Use

WordPress Login Loop Behind CDN or Proxy

WP “Menus Not Saving” — The Max Input Vars Killer

Post Views: 5

Post navigation

Git Hooks Automation: Pre-commit Checks That Save Hours of Debugging
Windows 11 WSL2: Run Linux at Native Speed Without Dual Boot

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

March 2026
M T W T F S S
 1
2345678
9101112131415
16171819202122
23242526272829
3031  
« Feb    

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (938)
  • How to add default value for Entity Framework migrations for DateTime and Bool (836)
  • Get the First and Last Word from a String or Sentence in SQL (828)
  • How to select distinct rows in a datatable in C# (801)
  • How to make theater mode the default for Youtube (736)
  • Add Constraint to SQL Table to ensure email contains @ (575)
  • How to enable, disable and check if Service Broker is enabled on a database in SQL Server (554)
  • Average of all values in a column that are not zero in SQL (523)
  • How to use Map Mode for Vertical Scroll Mode in Visual Studio (477)
  • Find numbers with more than two decimal places in SQL (441)

Recent Posts

  • C#: Saving Memory with yield return (Lazy Streams)
  • C#: Why Records are Better Than Classes for Data DTOs
  • C#: Creating Strings Without Memory Pressure with String.Create
  • SQL: Protecting Sensitive Data with Dynamic Data Masking
  • SQL: Writing Readable Queries with Common Table Expressions (CTE)
  • .NET Core: Handling Errors Gracefully with Middleware
  • .NET Core: Mastering Service Lifetimes (A Visual Guide)
  • Git: Surgical Stashing – Don’t Save Everything!
  • Git: Writing Commits That Your Future Self Won’t Hate
  • Ajax: Improving Perceived Speed with Skeleton Screens

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (938)
  • How to add default value for Entity Framework migrations for DateTime and Bool (836)
  • Get the First and Last Word from a String or Sentence in SQL (828)
  • How to select distinct rows in a datatable in C# (801)
  • How to make theater mode the default for Youtube (736)

Recent Posts

  • C#: Saving Memory with yield return (Lazy Streams)
  • C#: Why Records are Better Than Classes for Data DTOs
  • C#: Creating Strings Without Memory Pressure with String.Create
  • SQL: Protecting Sensitive Data with Dynamic Data Masking
  • SQL: Writing Readable Queries with Common Table Expressions (CTE)

Social

  • ErcanOPAK.com
  • GoodReads
  • LetterBoxD
  • Linkedin
  • The Blog
  • Twitter
© 2026 Bits of .NET | Built with Xblog Plus free WordPress theme by wpthemespace.com