<h1 id="id-layzrjs">Layzr.js</h1> <p><a href="https://www.npmjs.com/package/layzr.js"><img src="https://img.shields.io/npm/v/layzr.js.svg?style=flat-square" alt="Layzr.js on NPM"></a></p> <p>A modern lazy loading library for images.</p> <ul> <li><a href="http://callmecavs.github.io/layzr.js/">Demo Page</a></li> </ul> <h2 id="id-getting-started">Getting Started</h2> <p>Follow these steps:</p> <ol> <li><a href="#install">Install</a></li> <li><a href="#setup-images">Setup Images</a></li> <li><a href="#instantiate">Instantiate</a></li> <li><a href="#options">Review Options</a></li> <li><a href="#events">Review Events</a></li> <li><a href="#api">Review API</a></li> <li><strong><a href="https://github.com/callmecavs/layzr.js/tree/master/examples">Review Example Code</a></strong></li> </ol> <ul> <li>Examples progress like a coffee addiction: small -> medium -> large</li> </ul> <h2 id="id-install">Install</h2> <p>Layzr was developed with a modern JavaScript workflow in mind. Though not required, it's convenient to have a build system in place that can transpile ES6, and bundle modules. For a minimal boilerplate that does so, try <a href="https://github.com/callmecavs/outset">outset</a>.</p> <p>Choose an installation option based on your workflow:</p> <ul> <li><a href="#npm">npm</a></li> <li><a href="#cdn">CDN</a></li> <li><a href="#download">Download</a></li> <li><a href="#framework-bridge">Framework Bridge</a></li> </ul> <p>Refer to the <a href="https://github.com/callmecavs/layzr.js/releases">releases</a> page for version specific information.</p> <h3 id="id-npm">npm</h3> <p>Install Layzr, and add it to your <code>package.json</code> dependencies.</p> <pre><code>$ npm install layzr.js --save </code></pre> <p>Then <code>import</code> it into the file where you'll use it.</p> <pre><code class="hljs language-es6">import Layzr from 'layzr.js' </code></pre> <h3 id="id-cdn">CDN</h3> <p>Copy and paste one of the following <code><script></code> tags. Note the version number in the <code>src</code> attributes.</p> <h4 id="id-jsdelivr"><a href="http://www.jsdelivr.com/projects/layzr.js">jsDelivr</a></h4> <pre><code class="hljs language-html"><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/layzr.js/2.0.2/layzr.min.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span> </code></pre> <h4 id="id-cdnjs"><a href="https://cdnjs.com/libraries/layzr.js">cdnjs</a></h4> <pre><code class="hljs language-html"><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/layzr.js/2.0.2/layzr.min.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span> </code></pre> <h3 id="id-download">Download</h3> <p><a href="https://github.com/callmecavs/layzr.js/archive/master.zip">Download</a> the latest version, and load the script in the <code>dist</code> folder.</p> <pre><code class="hljs language-html"><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"layzr.min.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span> </code></pre> <h3 id="id-framework-bridge">Framework Bridge</h3> <p>Thank you to the community members who created these framework bridges!</p> <ul> <li>Ruby on Rails: <a href="https://github.com/mohitjain/layzr-rails">layzr-rails</a> by <a href="https://github.com/mohitjain">Mohit Jain</a></li> </ul> <h2 id="id-setup-images">Setup Images</h2> <p>Layzr intelligently chooses the best image source available <strong>based on an image's data attributes and browser feature detection</strong>.</p> <ul> <li>In browsers that <a href="http://caniuse.com/#search=srcset">support <code>srcset</code></a>, if available, it will be used to determine the source.</li> <li>In browsers that don't, the normal or retina source will be chosen based on the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio">devicePixelRatio</a> and availability.</li> </ul> <p>Note that all attribute names are configurable via the <a href="#options">options</a> passed to Layzr. To indicate potential sources, add the following attributes to your images:</p> <div class="table-responsive"><table class="table table-striped"><tr> <th align="left">Name</th> <th align="center">Required</th> <th align="center">Optional</th> </tr> <tr> <td align="left"><a href="#data-normal"><code>data-normal</code></a></td> <td align="center">✓</td> <td align="center"></td> </tr> <tr> <td align="left"><a href="#data-retina"><code>data-retina</code></a></td> <td align="center"></td> <td align="center">✓</td> </tr> <tr> <td align="left"><a href="#data-srcset"><code>data-srcset</code></a></td> <td align="center"></td> <td align="center">✓</td> </tr> </table></div><h3 id="id-data-normal">data-normal</h3> <p>Put the <em>normal resolution</em> source in the <code>data-normal</code> attribute.</p> <pre><code class="hljs language-html"><span class="hljs-tag"><<span class="hljs-name">img</span> <span class="hljs-attr">data-normal</span>=<span class="hljs-string">"normal.jpg"</span>></span> </code></pre> <p>Note that Layzr <strong>selects elements using this attribute</strong>. Elements without it won't be tracked, and will never load.</p> <h3 id="id-data-retina">data-retina</h3> <p>Add the <em>retina/high resolution</em> source in the <code>data-retina</code> attribute.</p> <pre><code class="hljs language-html"><span class="hljs-tag"><<span class="hljs-name">img</span> <span class="hljs-attr">data-normal</span>=<span class="hljs-string">"normal.jpg"</span> <span class="hljs-attr">data-retina</span>=<span class="hljs-string">"retina.jpg"</span>></span> </code></pre> <h3 id="id-data-srcset">data-srcset</h3> <p>Add the <em>source set</em> in the <code>data-srcset</code> attribute. For information on the proper syntax, read the official <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img">specification</a>.</p> <pre><code class="hljs language-html"><span class="hljs-tag"><<span class="hljs-name">img</span> <span class="hljs-attr">data-normal</span>=<span class="hljs-string">"normal.jpg"</span> <span class="hljs-attr">data-retina</span>=<span class="hljs-string">"retina.jpg"</span> <span class="hljs-attr">data-srcset</span>=<span class="hljs-string">"small.jpg 320w, medium.jpg 768w, large.jpg 1024w"</span>></span> </code></pre> <h2 id="id-instantiate">Instantiate</h2> <p>Create an instance, optionally passing in your <a href="#options">options</a>.</p> <p>Be sure to <strong>assign your Layzr instance to a variable</strong>. Using your instance, you can:</p> <ul> <li>start and stop the event listeners</li> <li>add and remove event handlers</li> <li>accommodate dynamically added elements</li> </ul> <pre><code class="hljs language-es6">// using the default options const instance = Layzr() // using custom options const instance = Layzr({ // ... }) </code></pre> <p>Options are explained in the following section.</p> <h2 id="id-options">Options</h2> <p>Default options are shown below, and an explanation of each follows:</p> <pre><code class="hljs language-es6">const instance = Layzr({ normal: 'data-normal', retina: 'data-retina', srcset: 'data-srcset', threshold: 0 }) </code></pre> <h3 id="id-normal">normal</h3> <p>Customize the attribute the normal resolution source is taken from.</p> <pre><code class="hljs language-es6">const instance = Layzr({ normal: 'data-normal' }) </code></pre> <h3 id="id-retina">retina</h3> <p>Customize the attribute the retina/high resolution source is taken from.</p> <pre><code class="hljs language-es6">const instance = Layzr({ retina: 'data-retina' }) </code></pre> <h3 id="id-srcset">srcset</h3> <p>Customize the attribute the source set is taken from.</p> <pre><code class="hljs language-es6">const instance = Layzr({ srcset: 'data-srcset' }) </code></pre> <h3 id="id-threshold">threshold</h3> <p>Adjust when images load, relative to the viewport. <em>Positive values make images load sooner, negative values make images load later</em>.</p> <p>Threshold is a percentage of the viewport height, identical to the CSS <code>vh</code> unit.</p> <pre><code class="hljs language-es6">const instance = Layzr({ threshold: 0 }) </code></pre> <h2 id="id-events">Events</h2> <p>Layzr instances are extended with <a href="https://github.com/callmecavs/knot.js">Knot.js</a>, a browser-based event emitter. Use the event emitter syntax to add and remove handlers. Review the emitter syntax <a href="https://github.com/callmecavs/knot.js#api">here</a>.</p> <p>Layzr emits the following events:</p> <ul> <li><a href="#srcbefore">src:before</a></li> <li><a href="#srcafter">src:after</a></li> </ul> <h3 id="id-srcbefore">src:before</h3> <p>This event is emitted immediately <em>before an image source is set</em>. The image node is passed to the event handler.</p> <pre><code class="hljs language-es6">instance.on('src:before', (element) => { // 'this' is your Layzr instance // 'element' is the image node // ... }) </code></pre> <p>Load event handlers should be attached using this event. See the <a href="https://github.com/callmecavs/layzr.js/blob/master/examples/large.js">example</a>, and note the <a href="https://api.jquery.com/load-event/">caveats</a> associated with image load events before proceeding.</p> <h3 id="id-srcafter">src:after</h3> <p>This event is emitted immediately <em>after an image source is set</em>. The image node is passed to the event handler.</p> <pre><code class="hljs language-es6">instance.on('src:after', (element) => { // 'this' is your Layzr instance // 'element' is the image node // ... }) </code></pre> <p>Note that the image is not necessarily done loading when this event fires.</p> <h2 id="id-api">API</h2> <p>All API methods are <strong>chainable</strong>, including those from the emitter.</p> <h3 id="id-handlersflag">.handlers(flag)</h3> <p>Add or remove the <code>scroll</code> and <code>resize</code> event handlers.</p> <pre><code class="hljs language-es6">instance .handlers(true) // 'true' adds them .handlers(false) // 'false' removes them </code></pre> <h3 id="id-check">.check()</h3> <p>Manually check if elements are in the viewport.</p> <p>This method is called while the <code>window</code> is scrolled or resized.</p> <pre><code class="hljs language-es6">instance.check() </code></pre> <h3 id="id-update">.update()</h3> <p>Update the elements Layzr is checking.</p> <pre><code class="hljs language-es6">instance.update() </code></pre> <p><strong>Dynamically added elements</strong> should be handled using this method. See the <a href="https://github.com/callmecavs/layzr.js/blob/master/examples/large.js">example</a>.</p> <h2 id="id-browser-support">Browser Support</h2> <p>Layzr depends on the following browser APIs:</p> <ul> <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/classList">classList</a></li> <li>ES5 array methods: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice">slice</a></li> <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame</a></li> </ul> <p>It supports the following natively:</p> <ul> <li>Chrome 24+</li> <li>Firefox 23+</li> <li>Safari 6.1+</li> <li>Opera 15+</li> <li>Edge 12+</li> <li>IE 10+</li> <li>iOS Safari 7.1+</li> <li>Android Browser 4.4+</li> </ul> <p>To support older browsers, consider including <a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills">polyfills/shims</a> for the APIs listed above. There are <strong>no plans to include any in the library</strong>, in the interest of file size.</p> <h2 id="id-colophon">Colophon</h2> <ul> <li>Site Design: <a href="https://dribbble.com/cp_allen">Chris Allen</a></li> <li>Stock Photos: <a href="https://unsplash.com/">Unsplash</a></li> </ul> <h2 id="id-license">License</h2> <p><a href="https://opensource.org/licenses/MIT">MIT</a>. © 2016 Michael Cavalea</p> <p><a href="http://forthebadge.com"><img src="http://forthebadge.com/images/badges/built-with-love.svg" alt="Built With Love"></a></p>