Lazy-load images
ImagesDefers off-screen images until they scroll into the viewport.
Filter
lazyload_images
· Filter docs
A mod_pagespeed 1.15 filter. ModPageSpeed 2.0 applies it as part of one always-on pipeline, not as a separate switch.
Both frames render identically — that's the goal. The win is in the bytes and requests
below, not the look. They're served live by mod_pagespeed 1.15 on
demo-httpd-1.1.modpagespeed.com; the optimized frame
applies only this filter. Right after a cache purge it may briefly match the original while
the worker rewrites it — reload to see the result.
This filter is beacon-driven: mod_pagespeed
instruments the page, a real browser reports back, then it serves the optimized form
and re-measures every few minutes — so the optimized frame can take a reload, or
briefly revert to the original, before it reflects the change.
Measured impact
HTTP requests
Total bytes
What changed in the source
The page's HTML, before and after this filter. Red lines are removed, green lines are added.
… 38 unchanged lines …
loaded once you scroll down.</p>
<p>*</p>
<p>*</p>
- <img src="images/Puzzle2.jpg" srcset="images/Puzzle.jpg 2x"><br/>
- <img src="images/IronChef2.gif"><br/>
- <img src="images/Cuppa.png"><br/>
- </body>
+ <script type="text/javascript" data-pagespeed-no-defer>//<![CDATA[ (function(){function f(a,b,c){if(a.addEventListener)a.addEventListener(b,c,!1);else if(a.attachEvent)a.attachEvent("on"+b,c);else{var d=a["on"+b];a["on"+b]=function(){c.call(this);d&&d.call(this)}}};window.pagespeed=window.pagespeed||{};var g=window.pagespeed;function k(a){this.l=[];this.j=0;this.m=!1;this.v=a;this.u=null;this.A=0;this.h=!1;this.g=0}function m(a,b){var c=b.getAttribute("data-pagespeed-lazy-position");if(c)return parseInt(c,0);c=b.offsetTop;var d=b.offsetParent;d&&(c+=m(a,d));c=Math.max(c,0);b.setAttribute("data-pagespeed-lazy-position",c);return c} function n(a,b){if(!a.h&&(b.offsetHeight==0||b.offsetWidth==0))return!1;var c=0;typeof window.pageYOffset=="number"?c=window.pageYOffset:document.body&&document.body.scrollTop?c=document.body.scrollTop:document.documentElement&&document.documentElement.scrollTop&&(c=document.documentElement.scrollTop);var d=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;var e=c;c+=d;var h=b.getBoundingClientRect();h?(c=h.top-d,e=h.bottom):(d=m(a,b),b=d+b.offsetHeight,c=d-c,e= b-e);return c<=a.j&&e+a.j>=0}
+ k.prototype.o=function(a){q(a);var b=this;window.setTimeout(function(){var c=a.getAttribute("data-pagespeed-lazy-src");if(c)if((b.m||n(b,a))&&a.src.indexOf(b.v)!=-1){var d=a.parentNode,e=a.nextSibling;d&&d.removeChild(a);a.i&&(a.getAttribute=a.i);a.removeAttribute("onload");if(a.tagName&&a.tagName=="IMG"&&g.CriticalImages){var h=!1,l=function(){h||(h=!0,b.h&&(b.g--,b.g==0&&g.CriticalImages.checkCriticalImages()))};f(a,"load",function(){g.CriticalImages.checkImageForCriticality(this);l()});f(a,"error",
+ function(){l()})}a.removeAttribute("data-pagespeed-lazy-src");a.removeAttribute("data-pagespeed-lazy-replaced-functions");d&&d.insertBefore(a,e);if(d=a.getAttribute("data-pagespeed-lazy-srcset"))a.srcset=d,a.removeAttribute("data-pagespeed-lazy-srcset");a.src=c}else b.l.push(a)},0)};k.prototype.loadIfVisibleAndMaybeBeacon=k.prototype.o;k.prototype.B=function(){this.m=!0;r(this);for(var a=document.getElementsByTagName("img"),b=0,c;c=a[b];b++)t(c,"data-pagespeed-lazy-src")&&this.o(c)};
+ k.prototype.loadAllImages=k.prototype.B;function r(a){var b=a.l,c=b.length;a.l=[];for(var d=0;d<c;++d)a.o(b[d])}function t(a,b){return a.g?a.g(b)!=null:a.getAttribute(b)!=null}k.prototype.C=function(){for(var a=document.getElementsByTagName("img"),b=0,c;c=a[b];b++)t(c,"data-pagespeed-lazy-src")&&q(c)};k.prototype.overrideAttributeFunctions=k.prototype.C; function q(a){t(a,"data-pagespeed-lazy-replaced-functions")||(a.i=a.getAttribute,a.getAttribute=function(b){b.toLowerCase()=="src"&&t(this,"data-pagespeed-lazy-src")&&(b="data-pagespeed-lazy-src");return this.i(b)},a.setAttribute("data-pagespeed-lazy-replaced-functions","1"))} g.D=function(a,b){function c(){if(!(d.h&&a||d.u)){var e=200;(new Date).getTime()-d.A>200&&(e=0);d.u=window.setTimeout(function(){d.A=(new Date).getTime();r(d);d.u=null},e)}}var d=new k(b);g.lazyLoadImages=d;f(window,"load",function(){d.h=!0;d.m=a;d.j=200;if(g.CriticalImages){for(var e=0,h=document.getElementsByTagName("img"),l=0,p;p=h[l];l++)p.src.indexOf(d.v)!=-1&&t(p,"data-pagespeed-lazy-src")&&e++;d.g=e;d.g==0&&g.CriticalImages.checkCriticalImages()}r(d)});b.indexOf("data:")!=0&&((new Image).src=
+ b);f(window,"scroll",c);f(window,"resize",c)};g.lazyLoadInit=g.D;})();
+
+ pagespeed.lazyLoadInit(true, "/pagespeed_static/1.JiBnMqyl6S.gif");
+
+ //]]></script><img data-pagespeed-lazy-src="images/Puzzle2.jpg" data-pagespeed-lazy-srcset="images/Puzzle.jpg 2x" src="/pagespeed_static/1.JiBnMqyl6S.gif" onload="pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);" onerror="this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);"><br/>
+ <img data-pagespeed-lazy-src="images/IronChef2.gif" src="/pagespeed_static/1.JiBnMqyl6S.gif" onload="pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);" onerror="this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);"><br/>
+ <img data-pagespeed-lazy-src="images/Cuppa.png" src="/pagespeed_static/1.JiBnMqyl6S.gif" onload="pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);" onerror="this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);"><br/>
+ <script type="text/javascript" data-pagespeed-no-defer>pagespeed.lazyLoadImages.overrideAttributeFunctions();</script></body>
</html>
Run this on your own site
This is one of 49 filters mod_pagespeed 1.15 applies in place — self-hosted on
Apache, nginx, and IIS. Install and run it: it optimizes right away and adds an
X-PageSpeed-Warn: unlicensed header until you license it.
Production use requires a commercial license — but the software never locks you out.