Lazy Load Breaking Images β Showing Placeholder Only: Causes and Fixes
You enable lazy loading to speed up your site. Visitors arrive and see broken images or spinning loaders that never finish. You log in as admin and images work fine. The source code shows a base64 placeholder where the image URL should be. Welcome to the lazy load paradox. Here's what's actually happeningβand how to fix it.
Why Lazy Load Breaks Images
Lazy loading isn't broken. But it breaks when multiple plugins fight over control, or when your setup doesn't match your lazy load settings. Here's what goes wrong:
1. Multiple Lazy Load Plugins Enabled (The #1 Cause)
Every plugin tries to rewrite image tags. When two plugins do this simultaneously, they conflict.
Real-world example: You have WP Rocket (lazy load enabled) + Smush (lazy load enabled) + Jetpack (lazy images enabled) + a custom theme (native lazy load). Each one adds its own lazy load attributes. Images end up with conflicting instructions, and the last one to run might break them all.
What happens:
- WP Rocket rewrites
srcβdata-src - Smush sees the broken tag and tries to "fix" it, moving data-src β data-lazyload
- Browser can't find
srcordata-srcordata-lazyload - Image never loads; placeholder stays forever
2. Caching Layer Stripping Lazy Load Attributes
Some caching plugins minify or optimize HTML and accidentally remove lazy load attributes.
Example: WP Total Cache or server-level cache + lazy load plugin. Cache is built with lazy load enabled, then a cached page is served without the lazy load JS that loads the actual images. Result: placeholder forever.
3. JavaScript Not Loading for Visitors (Working for Admins)
Lazy load plugins need JavaScript to run. Some plugins only load that JS for logged-in users.
Real case: Smush's lazy load works perfectly when you're logged in. You log out, reloadβimages are stuck on placeholder. Why? Smush loads its JavaScript in the admin footer by default, but might not load it properly for visitors if the script is deferred or async-loaded and JavaScript execution is blocked.
Or: A security or cookie plugin blocks the JavaScript that loads images until consent is given. Images stay stuck on placeholder until the user accepts cookies.
4. Images Have No Width/Height Attributes
Modern lazy load plugins (especially those with responsive placeholders or blurhash) need width and height in the image tag.
Example: Gutenberg doesn't add width/height by default. Lazy load plugin can't generate a proper placeholder size. Image loads at wrong dimensions, or JavaScript fails silently and never swaps the placeholder.
HTML comparison:
Good (will lazy load):
<img src="image.jpg" width="800" height="600" loading="lazy" alt="...">
Bad (lazy load may fail):
<img src="image.jpg" loading="lazy" alt="...">
5. Conflict With Page Builder Images (Elementor, GenerateBlocks, Etc.)
Page builders generate their own image markup with custom data attributes. Lazy load plugins don't recognize these custom formats.
Example: Elementor stores image URLs in data-elementor-src. Lazy load plugin looks for src or data-src and doesn't find it. Image stays as placeholder or doesn't load at all.
6. Base64 Placeholder Stuck in HTML
When lazy load converts images, it swaps src with a tiny transparent 1x1 pixel base64 image:
src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
The JavaScript that's supposed to replace this with the real image URL doesn't run, crashes, or doesn't load. Image stays as that invisible placeholder forever.
Diagnosis: Is It Really Lazy Load?
Step 1: Check your browser's developer tools
- Open any page with a broken image
- Right-click the broken image β Inspect
- Look at the
<img>tag'ssrcattribute - If it's a base64 data URI or a placeholder image URL, lazy load is the culprit
- If there's a
data-srcattribute with the real URL, lazy load is enabled but the JavaScript isn't loading
Step 2: Log out and test as a visitor
Clear cookies, open a private browser window, visit your site. Do images load? If yes for admin, no for visitors, JavaScript isn't running for public users.
Step 3: Disable lazy load and test
- Go to Settings β [Lazy Load Plugin] (WP Rocket, Smush, etc.)
- Disable lazy load for images
- Clear cache (hard refresh: Ctrl+Shift+R or Cmd+Shift+R)
- Visit the page
- Do images load? If yes, lazy load was breaking them.
Quick Fixes (Do These First)
Fix #1: Disable Lazy Load on ALL But ONE Plugin
Pick one plugin to handle lazy load. Disable it everywhere else.
Recommended order of priority:
- Keep: WP Rocket (most reliable, integrates well)
- Disable in: Smush, Jetpack, LiteSpeed Cache, W3 Total Cache
Or if you prefer Smush:
- Keep: Smush (image optimization + lazy load)
- Disable in: WP Rocket, Jetpack, LiteSpeed Cache
How to disable:
- WP Rocket: Settings β WP Rocket β Media β uncheck "Enable Lazy Load"
- Smush: Dashboard β Smush β Lazy Load β toggle off
- Jetpack: Settings β Jetpack β Performance β uncheck "Lazy Load Images"
- LiteSpeed Cache: Settings β LiteSpeed Cache β Image β uncheck "Lazy Load"
Fix #2: Clear All Caches After Disabling
Lazy load changes are often cached. Images may still appear broken even after disabling.
Clear these in order:
- Plugin cache (WP Rocket β Clear Cache; Smush β Clear Cache)
- Browser cache (Ctrl+Shift+Delete β Clear browsing data)
- Server cache (if you have access via cPanel β Clear Cache)
- CDN cache (if using Cloudflare β Purge Cache)
- Hard refresh the page (Ctrl+Shift+R)
Fix #3: Exclude Specific Images From Lazy Load
Sometimes only certain images break. Exclude them from lazy loading.
In WP Rocket:
- Settings β WP Rocket β Media β Lazy Load
- Scroll to "Exclude images"
- Add the image URL or CSS class to exclude
In Smush:
- Dashboard β Smush β Lazy Load Settings
- "Exclude images by class/ID"
- Add the class or ID of broken images
For page builder images (Elementor, GenerateBlocks): Exclude by adding this CSS class or ID to the plugin's exclusion list:
elementor-image
generateblocks-image
spectra-image
Fix #4: Enable Native Lazy Loading Only (Minimal)
WordPress 5.5+ has built-in lazy loading. It's simple and less prone to breaking.
To use WordPress native lazy load:
- Disable all third-party lazy load plugins
- WordPress automatically adds
loading="lazy"to images - Modern browsers handle it natively
Trade-off: Native lazy load is less customizable but more reliable. You can't add placeholder images or fine-tune load triggers. But images will actually load.
Fix #5: Disable Lazy Load for Specific Pages
If lazy load breaks only on certain pages (portfolios, galleries), disable it just for those.
Via plugin settings (if available):
- WP Rocket β Media β Lazy Load β "Disable Lazy Load on" β add page ID
- Smush β Lazy Load β exclude by page URL
Via code (add to wp-config.php):
// Disable lazy load on portfolio page (ID: 42)
define('WP_ROCKET_DISABLE_LAZY_LOAD', true);
// Then re-enable on other pages
Advanced Fixes (If Quick Fixes Don't Work)
6. Check for JavaScript Errors Blocking Lazy Load
Lazy load relies on JavaScript. If another script crashes, lazy load doesn't run.
Debug:
- Open DevTools (F12)
- Go to Console tab
- Look for red errors
- Common culprits: security plugins, poorly coded theme, conflicting plugins
- Disable plugins one by one until errors stop
7. Disable Cookie Consent Plugin Temporarily
Cookie consent plugins often block scripts until users accept cookies. Lazy load JS is frequently blocked.
Test:
- Temporarily disable your cookie consent plugin (CookieYes, Cookiebot, etc.)
- Clear cache and reload
- Do images load?
- If yes, add lazy load scripts to the cookie plugin's "Always allow" list
8. Add Width/Height to Images (For Responsive Placeholders)
If using a fancy lazy load plugin with blur placeholders, all images need width/height.
Manually for key images: Edit each image in the media library and set "Attachment Details" β Width/Height.
Automatically via plugin: Use Regenerate Thumbnails or an auto-dimension plugin to add width/height to all images.
9. Check for Theme/Plugin-Level Lazy Load Settings
Some themes (Elementor-based, GeneratePress, Blocksy) have their own lazy load option.
Check these:
- Your theme settings (if it has a performance or images section)
- Theme's Customizer β Image settings
- Page builder settings (Elementor, GenerateBlocks, etc.)
If the theme has lazy load, disable it and let WP Rocket or Smush handle it.
10. Switch Lazy Load Plugins
If WP Rocket's lazy load breaks images, try Smush. If Smush breaks them, try native lazy load or a lightweight plugin.
Tested lazy load plugins (most reliable):
- WP Rocket β Most reliable (has paid support)
- Smush Pro β Good, but conflicts with other image plugins
- Native (WordPress 5.5+) β Simplest, no plugin needed
- LiteSpeed Cache β Good if you use LiteSpeed hosting
- Avoid: Old standalone lazy load plugins (outdated, often broken)
Prevention: Keep Lazy Load Working
1. One lazy load plugin per site β Pick one (WP Rocket or Smush) and disable lazy load everywhere else.
2. Update your plugins regularly β Lazy load conflicts are fixed in updates. Outdated plugins = broken images.
3. Test after updates β Each plugin update might change how lazy load works. After updating WP, plugins, or theme, do a quick check: open a page, scroll, confirm images load.
4. Add width/height to images during upload β Use a plugin to auto-add dimensions, or manually set them in the media library.
5. Don't use both page builder lazy load AND plugin lazy load β Choose one. If using Elementor, disable its lazy load and let WP Rocket handle it globally.
6. Keep lazy load off above-the-fold images β Hero images, logos, and critical images should load immediately, not lazy. Exclude them by class or ID.
7. Monitor your site after enabling lazy load β Test across devices (mobile, desktop), different browsers (Chrome, Firefox, Safari), and as both logged-in and logged-out user.
The Real Talk
Lazy load is great for performance. But it's also a place where plugins love to fight, and where a single setting can break every image on your site.
The fix is almost always the same: disable lazy load in all plugins except one, clear caches completely, and test. If images still don't load, switch to native WordPress lazy load or try a different plugin.
Lazy load breaking images is rarely a bugβit's usually you (or your plugin stack) fighting against itself. One plugin, proper cache clearing, and you're done.
Last updated: October 2026. Data: WP Rocket + Smush conflicts (2023β2026), Jetpack + Smush + WP Total Cache conflicts, cookie consent + lazy load issues, Elementor image tag conflicts, base64 placeholder issues in forum threads 2020β2026.
