├── README.md ├── demo ├── 1.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg ├── blank.gif └── mobile │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ └── 5.jpg ├── gh-page ├── fauxconsole.css ├── fauxconsole.js ├── pygment_trac.css ├── scale.fix.js └── styles.css ├── index.html └── javascripts ├── lazyload.js └── lazyload.min.js /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | Lazy load your images without the overhead of a framework. Optionally, send mobile-optimized images to smaller screens. Tested on IE7+, Firefox, Chrome, Safari, iOS. 4 | 5 | Based on code from [Mike Pulaski](http://www.mikepulaski.com/code/2012/06/29/lazy-load-images-without-external-libraries/). 6 | 7 | # Usage 8 | 9 | 1) Include `lazyload.min.js` or inline it. 10 | 11 | 2) Add `.lazy-load` and `data-src` to each of your `` tags. Optionally add `data-src-mobile`, a placeholder src, and a fallback image. 12 | 13 | ```html 14 | 15 | 16 | ``` 17 | 18 | 3) Add CSS3 magic for an animated fade-in: 19 | 20 | ```css 21 | .lazy-load, .lazy-loaded { 22 | -webkit-transition: opacity 0.3s; 23 | -moz-transition: opacity 0.3s; 24 | -ms-transition: opacity 0.3s; 25 | -o-transition: opacity 0.3s; 26 | transition: opacity 0.3s; 27 | opacity: 0; 28 | } 29 | 30 | .lazy-loaded { opacity: 1; } 31 | ``` 32 | 33 | # Demo 34 | 35 | http://kaizau.github.com/Lazy-Load-Images-without-jQuery/ 36 | -------------------------------------------------------------------------------- /demo/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/1.jpg -------------------------------------------------------------------------------- /demo/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/2.jpg -------------------------------------------------------------------------------- /demo/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/3.jpg -------------------------------------------------------------------------------- /demo/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/4.jpg -------------------------------------------------------------------------------- /demo/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/5.jpg -------------------------------------------------------------------------------- /demo/blank.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/blank.gif -------------------------------------------------------------------------------- /demo/mobile/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/mobile/1.jpg -------------------------------------------------------------------------------- /demo/mobile/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/mobile/2.jpg -------------------------------------------------------------------------------- /demo/mobile/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/mobile/3.jpg -------------------------------------------------------------------------------- /demo/mobile/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/mobile/4.jpg -------------------------------------------------------------------------------- /demo/mobile/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaizau/Lazy-Load-Images-without-jQuery/15cee06d31293353c41ae054177526d79b1bde97/demo/mobile/5.jpg -------------------------------------------------------------------------------- /gh-page/fauxconsole.css: -------------------------------------------------------------------------------- 1 | #fauxconsole{ 2 | position:absolute; 3 | top:0; 4 | right:0; 5 | width:300px; 6 | border:1px solid #999; 7 | font-family:courier,monospace; 8 | background:#eee; 9 | font-size:10px; 10 | padding:10px; 11 | } 12 | html>body #fauxconsole{ 13 | position:fixed; 14 | } 15 | #fauxconsole a{ 16 | float:right; 17 | padding-left:1em; 18 | padding-bottom:.5em; 19 | text-align:right; 20 | } 21 | -------------------------------------------------------------------------------- /gh-page/fauxconsole.js: -------------------------------------------------------------------------------- 1 | /* Faux Console by Chris Heilmann http://wait-till-i.com */ if(!window.console){var console={init:function(){console.d=document.createElement('div');document.body.appendChild(console.d);var a=document.createElement('a');a.href='javascript:console.hide()';a.innerHTML='close';console.d.appendChild(a);var a=document.createElement('a');a.href='javascript:console.clear();';a.innerHTML='clear';console.d.appendChild(a);var id='fauxconsole';if(!document.getElementById(id)){console.d.id=id;}console.hide();},hide:function(){console.d.style.display='none';},show:function(){console.d.style.display='block';},log:function(o){console.d.innerHTML+='
'+o;console.show();},clear:function(){console.d.parentNode.removeChild(console.d);console.init();console.show();},/*Simon Willison rules*/addLoadEvent:function(func){var oldonload=window.onload;if(typeof window.onload!='function'){window.onload=func;}else{window.onload=function(){if(oldonload){oldonload();}func();}};}};console.addLoadEvent(console.init);} -------------------------------------------------------------------------------- /gh-page/pygment_trac.css: -------------------------------------------------------------------------------- 1 | .highlight { background: #ffffff; } 2 | .highlight .c { color: #999988; font-style: italic } /* Comment */ 3 | .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ 4 | .highlight .k { font-weight: bold } /* Keyword */ 5 | .highlight .o { font-weight: bold } /* Operator */ 6 | .highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */ 7 | .highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ 8 | .highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */ 9 | .highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ 10 | .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ 11 | .highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ 12 | .highlight .ge { font-style: italic } /* Generic.Emph */ 13 | .highlight .gr { color: #aa0000 } /* Generic.Error */ 14 | .highlight .gh { color: #999999 } /* Generic.Heading */ 15 | .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ 16 | .highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ 17 | .highlight .go { color: #888888 } /* Generic.Output */ 18 | .highlight .gp { color: #555555 } /* Generic.Prompt */ 19 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 20 | .highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */ 21 | .highlight .gt { color: #aa0000 } /* Generic.Traceback */ 22 | .highlight .kc { font-weight: bold } /* Keyword.Constant */ 23 | .highlight .kd { font-weight: bold } /* Keyword.Declaration */ 24 | .highlight .kn { font-weight: bold } /* Keyword.Namespace */ 25 | .highlight .kp { font-weight: bold } /* Keyword.Pseudo */ 26 | .highlight .kr { font-weight: bold } /* Keyword.Reserved */ 27 | .highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */ 28 | .highlight .m { color: #009999 } /* Literal.Number */ 29 | .highlight .s { color: #d14 } /* Literal.String */ 30 | .highlight .na { color: #008080 } /* Name.Attribute */ 31 | .highlight .nb { color: #0086B3 } /* Name.Builtin */ 32 | .highlight .nc { color: #445588; font-weight: bold } /* Name.Class */ 33 | .highlight .no { color: #008080 } /* Name.Constant */ 34 | .highlight .ni { color: #800080 } /* Name.Entity */ 35 | .highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */ 36 | .highlight .nf { color: #990000; font-weight: bold } /* Name.Function */ 37 | .highlight .nn { color: #555555 } /* Name.Namespace */ 38 | .highlight .nt { color: #000080 } /* Name.Tag */ 39 | .highlight .nv { color: #008080 } /* Name.Variable */ 40 | .highlight .ow { font-weight: bold } /* Operator.Word */ 41 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 42 | .highlight .mf { color: #009999 } /* Literal.Number.Float */ 43 | .highlight .mh { color: #009999 } /* Literal.Number.Hex */ 44 | .highlight .mi { color: #009999 } /* Literal.Number.Integer */ 45 | .highlight .mo { color: #009999 } /* Literal.Number.Oct */ 46 | .highlight .sb { color: #d14 } /* Literal.String.Backtick */ 47 | .highlight .sc { color: #d14 } /* Literal.String.Char */ 48 | .highlight .sd { color: #d14 } /* Literal.String.Doc */ 49 | .highlight .s2 { color: #d14 } /* Literal.String.Double */ 50 | .highlight .se { color: #d14 } /* Literal.String.Escape */ 51 | .highlight .sh { color: #d14 } /* Literal.String.Heredoc */ 52 | .highlight .si { color: #d14 } /* Literal.String.Interpol */ 53 | .highlight .sx { color: #d14 } /* Literal.String.Other */ 54 | .highlight .sr { color: #009926 } /* Literal.String.Regex */ 55 | .highlight .s1 { color: #d14 } /* Literal.String.Single */ 56 | .highlight .ss { color: #990073 } /* Literal.String.Symbol */ 57 | .highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */ 58 | .highlight .vc { color: #008080 } /* Name.Variable.Class */ 59 | .highlight .vg { color: #008080 } /* Name.Variable.Global */ 60 | .highlight .vi { color: #008080 } /* Name.Variable.Instance */ 61 | .highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ 62 | 63 | .type-csharp .highlight .k { color: #0000FF } 64 | .type-csharp .highlight .kt { color: #0000FF } 65 | .type-csharp .highlight .nf { color: #000000; font-weight: normal } 66 | .type-csharp .highlight .nc { color: #2B91AF } 67 | .type-csharp .highlight .nn { color: #000000 } 68 | .type-csharp .highlight .s { color: #A31515 } 69 | .type-csharp .highlight .sc { color: #A31515 } 70 | -------------------------------------------------------------------------------- /gh-page/scale.fix.js: -------------------------------------------------------------------------------- 1 | var metas = document.getElementsByTagName('meta'); 2 | var i; 3 | if (navigator.userAgent.match(/iPhone/i)) { 4 | for (i=0; i 2 | 3 | 4 | 5 | 6 | 7 | 8 | Lazy load images without jQuery. by kaizau 9 | 10 | 11 | 12 | 13 | 16 | 17 | 31 | 32 | 35 | 36 | 37 | 38 |
39 |
40 |

Lazy load images without jQuery.

41 |

A totally lame name for a totally useful script.

42 | 43 |

View the Project on GitHub kaizau/Lazy-Load-Images-without-jQuery

44 | 45 | 50 |
51 |
52 | 53 |

About

54 |

Lazy load your images without the overhead of a framework. Optionally, send mobile-optimized images to smaller screens. Tested on IE7+, Firefox, Chrome, iOS.

55 | 56 |

Based on code from Mike Pulaski.

57 | 58 |

Usage

59 | 60 |
    61 |
  1. Include lazyload.min.js or inline it.

  2. 62 |
  3. 63 |

    Add .lazy-load and data-src to each of your <img> tags. Optionally add data-src-mobile, a placeholder src, and a fallback image.

    64 |
    65 |
    <img class="lazy-load" data-src="lazy.jpg" data-src-mobile="lazy-small.jpg" src="blank.gif" />
     66 | <noscript><img src="lazy.jpg" /></noscript>
     67 | 
    68 |
    69 |
  4. 70 |
  5. 71 |

    Add CSS3 for an animated fade-in.

    72 |
    73 |
    .lazy-load, .lazy-loaded {
     74 |   -webkit-transition: opacity 0.3s;
     75 |   -moz-transition: opacity 0.3s;
     76 |   -ms-transition: opacity 0.3s;
     77 |   -o-transition: opacity 0.3s;
     78 |   transition: opacity 0.3s;
     79 |   opacity: 0;
     80 | }
     81 | 
     82 | .lazy-loaded { opacity: 1; }
     83 | 
    84 |
    85 |
  6. 86 |
87 | 88 |
89 |

Demo

90 |

Open up your Developer Tools / Firebug to peek at the network.

91 |

On mobile, image order will be swapped (different images used).

92 |

Images courtesy of NASA.

93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 |
109 | 110 |
111 | 115 |
116 | 117 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /javascripts/lazyload.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Lazy Load Images without jQuery 3 | * http://kaizau.github.com/Lazy-Load-Images-without-jQuery/ 4 | * 5 | * Original by Mike Pulaski - http://www.mikepulaski.com 6 | * Modified by Kai Zau - http://kaizau.com 7 | */ 8 | (function() { 9 | var addEventListener = window.addEventListener || function(n,f) { window.attachEvent('on'+n, f); }, 10 | removeEventListener = window.removeEventListener || function(n,f,b) { window.detachEvent('on'+n, f); }; 11 | 12 | var lazyLoader = { 13 | cache: [], 14 | mobileScreenSize: 500, 15 | //tinyGif: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==', 16 | 17 | addObservers: function() { 18 | addEventListener('scroll', lazyLoader.throttledLoad); 19 | addEventListener('resize', lazyLoader.throttledLoad); 20 | }, 21 | 22 | removeObservers: function() { 23 | removeEventListener('scroll', lazyLoader.throttledLoad, false); 24 | removeEventListener('resize', lazyLoader.throttledLoad, false); 25 | }, 26 | 27 | throttleTimer: new Date().getTime(), 28 | 29 | throttledLoad: function() { 30 | var now = new Date().getTime(); 31 | if ((now - lazyLoader.throttleTimer) >= 200) { 32 | lazyLoader.throttleTimer = now; 33 | lazyLoader.loadVisibleImages(); 34 | } 35 | }, 36 | 37 | loadVisibleImages: function() { 38 | var scrollY = window.pageYOffset || document.documentElement.scrollTop; 39 | var pageHeight = window.innerHeight || document.documentElement.clientHeight; 40 | var range = { 41 | min: scrollY - 200, 42 | max: scrollY + pageHeight + 200 43 | }; 44 | 45 | var i = 0; 46 | while (i < lazyLoader.cache.length) { 47 | var image = lazyLoader.cache[i]; 48 | var imagePosition = getOffsetTop(image); 49 | var imageHeight = image.height || 0; 50 | 51 | if ((imagePosition >= range.min - imageHeight) && (imagePosition <= range.max)) { 52 | var mobileSrc = image.getAttribute('data-src-mobile'); 53 | 54 | image.onload = function() { 55 | this.className = this.className.replace(/(^|\s+)lazy-load(\s+|$)/, '$1lazy-loaded$2'); 56 | }; 57 | 58 | if (mobileSrc && screen.width <= lazyLoader.mobileScreenSize) { 59 | image.src = mobileSrc; 60 | } 61 | else { 62 | image.src = image.getAttribute('data-src'); 63 | } 64 | 65 | image.removeAttribute('data-src'); 66 | image.removeAttribute('data-src-mobile'); 67 | 68 | lazyLoader.cache.splice(i, 1); 69 | continue; 70 | } 71 | 72 | i++; 73 | } 74 | 75 | if (lazyLoader.cache.length === 0) { 76 | lazyLoader.removeObservers(); 77 | } 78 | }, 79 | 80 | init: function() { 81 | // Patch IE7- (querySelectorAll) 82 | if (!document.querySelectorAll) { 83 | document.querySelectorAll = function(selector) { 84 | var doc = document, 85 | head = doc.documentElement.firstChild, 86 | styleTag = doc.createElement('STYLE'); 87 | head.appendChild(styleTag); 88 | doc.__qsaels = []; 89 | styleTag.styleSheet.cssText = selector + "{x:expression(document.__qsaels.push(this))}"; 90 | window.scrollBy(0, 0); 91 | return doc.__qsaels; 92 | } 93 | } 94 | 95 | addEventListener('load', function _lazyLoaderInit() { 96 | var imageNodes = document.querySelectorAll('img[data-src]'); 97 | 98 | for (var i = 0; i < imageNodes.length; i++) { 99 | var imageNode = imageNodes[i]; 100 | 101 | // Add a placeholder if one doesn't exist 102 | //imageNode.src = imageNode.src || lazyLoader.tinyGif; 103 | 104 | lazyLoader.cache.push(imageNode); 105 | } 106 | 107 | lazyLoader.addObservers(); 108 | lazyLoader.loadVisibleImages(); 109 | 110 | removeEventListener('load', _lazyLoaderInit, false); 111 | }); 112 | } 113 | } 114 | 115 | // For IE7 compatibility 116 | // Adapted from http://www.quirksmode.org/js/findpos.html 117 | function getOffsetTop(el) { 118 | var val = 0; 119 | if (el.offsetParent) { 120 | do { 121 | val += el.offsetTop; 122 | } while (el = el.offsetParent); 123 | return val; 124 | } 125 | } 126 | 127 | lazyLoader.init(); 128 | })(); 129 | -------------------------------------------------------------------------------- /javascripts/lazyload.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Lazy Load Images without jQuery 3 | * http://kaizau.github.com/Lazy-Load-Images-without-jQuery/ 4 | * 5 | * Original by Mike Pulaski - http://www.mikepulaski.com 6 | * Modified by Kai Zau - http://kaizau.com 7 | */ 8 | !function(){function d(a){var b=0;if(a.offsetParent){do b+=a.offsetTop;while(a=a.offsetParent);return b}}var a=window.addEventListener||function(a,b){window.attachEvent("on"+a,b)},b=window.removeEventListener||function(a,b){window.detachEvent("on"+a,b)},c={cache:[],mobileScreenSize:500,addObservers:function(){a("scroll",c.throttledLoad),a("resize",c.throttledLoad)},removeObservers:function(){b("scroll",c.throttledLoad,!1),b("resize",c.throttledLoad,!1)},throttleTimer:(new Date).getTime(),throttledLoad:function(){var a=(new Date).getTime();a-c.throttleTimer>=200&&(c.throttleTimer=a,c.loadVisibleImages())},loadVisibleImages:function(){for(var a=window.pageYOffset||document.documentElement.scrollTop,b=window.innerHeight||document.documentElement.clientHeight,e={min:a-200,max:a+b+200},f=0;f=e.min-i&&h<=e.max){var j=g.getAttribute("data-src-mobile");g.onload=function(){this.className=this.className.replace(/(^|\s+)lazy-load(\s+|$)/,"$1lazy-loaded$2")},g.src=j&&screen.width<=c.mobileScreenSize?j:g.getAttribute("data-src"),g.removeAttribute("data-src"),g.removeAttribute("data-src-mobile"),c.cache.splice(f,1)}else f++}0===c.cache.length&&c.removeObservers()},init:function(){document.querySelectorAll||(document.querySelectorAll=function(a){var b=document,c=b.documentElement.firstChild,d=b.createElement("STYLE");return c.appendChild(d),b.__qsaels=[],d.styleSheet.cssText=a+"{x:expression(document.__qsaels.push(this))}",window.scrollBy(0,0),b.__qsaels}),a("load",function d(){for(var a=document.querySelectorAll("img[data-src]"),e=0;e