Thursday, December 4, 2014

Lazy Loading of Images With JavaScript and JQuery (a Plugin)

Intro

Have you noticed a growing number of websites that load images while you are scrolling down the page? Even if you haven't, just pretend that you have, or hey read on anyways! I'll try to entertain you. These pages are using a technique called lazy loading for the images. Your browser does not download the image until the image is at or near the viewport (not downloaded until you the client need to see the image), thus potentially saving on bandwidth and initial page display time for the user. Under the assumption that most visitors won't view every image in a large scrollable list, this can be quite a boon for you (the host) and for your users (the clients). If you're intrigued and want to read about one way to accomplish this feat, read on!

How to use the plug-in

There are quite a number of ways to lazy load images, but for this article I'll focus on just one. A JQuery plugin named unveil by Luis Almeida. For those of you unfamiliar with JQuery, I suggest you read up about it on their website before continuing. It will help you to have a basic understanding of what it does and how it works. If you want just the cliff-notes version, it's a lightweight (small download size) JavaScript library that handles a multitude of tedious tasks for you, and it has a very vibrant ecosystem of plugins from thousands of contributors.

Back to unveil...this plugin lets you specify a placeholder image for images as well as the final lazy-loaded ultimate image that the user will see. It's got just a couple other configuration options, but you can read about those on the unveil site linked below. We'll use it in it's most basic capacity, downloading an image lazily when the user scrolls down to that portion of the page. So, let's see how to use it.

Fire up your favorite html editor and create yourself an html page. Paste the content you see below into your html file:

<!DOCTYPE html>
<html>
 <head>
  <!-- link to jquery library hosted by google -->
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <!-- link to unveil library in the same directory as this html file -->
  <script src="jquery.unveil.js"></script>
 </head>
 <body>
  <div style="height: 1000px;">
   hi!
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="http://digitalis.nwp.org/sites/default/files/stuff_1.png" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="http://static.tumblr.com/429df189c9e81bb388196fb442db77ba/vbdvuoy/xrUmksw6n/tumblr_static_green-stuff.jpg" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="http://images.electricpig.co.uk/wp-content/uploads/2012/01/internet-stuff.jpg" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcT3WjcjnXnXG3MIZZ1rw3dQsjrx-06ogqZbcjArDwM3n1Q9ixrwCw" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="http://www.abc.net.au/tv/stuff/stuff_wendy.jpg" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ-5Ud4e36C7a9xsXgKr6ETuuecqSNorBhiWWelWj4UyfIUzzUwHg" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="http://tosaenglish.com/wp-content/uploads/2012/06/image.png" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="http://www.seren.bangor.ac.uk/wp-content/uploads/2012/10/story-of-stuff-book-adds-to-the-vision-of-decreased-consumption.jpeg" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="http://i.imgur.com/c6D2qCb.jpg" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="http://sd.keepcalm-o-matic.co.uk/i/keep-calm-and-stop-saving-stuff-on-desktop.png" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSvKoJ_CqT0yZQFelslk6DUralqV73_SfzuiTa30e6YC1cLzkxY" />
  </div>
  <div>
   <img src="http://www.clker.com/cliparts/v/W/8/R/B/w/blue-circle-th.png" 
    data-src="https://lh4.googleusercontent.com/-ZknF9DJA52o/AAAAAAAAAAI/AAAAAAAAAB4/JKBNFb96bM0/photo.jpg" />
  </div>
  <script>
   $(document).ready(function() {
     $("img").unveil(-400);
   });
  </script>
 </body>
</html>

Let's go over this code in sections. The first section I want to talk about is the "<head>" section of the html file. The important bits are the 2 script links. The first one links to a version of JQuery hosted by google servers. The 2nd script links to a js file that is expected to exist in the same location as your html file. Save the unveil js file to your hard drive in the same place where you have the html file.

The next part to talk about is all them thar div tags. The first one makes sure we have 1000 pixels taken up by useless stuff. I did this so that you could better play with the scrolling effect of lazy loaded images. The remaining divs are all containers for img tags. For those of you used to using img tags already, you know what the src attribute is; it's the url of the image to display. In the case of the above img tags, we're linking to a single placeholder image file which is a blue circle. Each of these img tags also contains a special data-src attribute which in the case of the unveil JQuery plugin, contains the image that will be downloaded and displayed when the user's viewport scrolls the image into view. Long story short, this is the image you'll actually see.

The last chunk of code I want to discuss is the final script tag. This contains our jquery function (the document.ready) which fires off when the document has finished loading. Our function above will apply the unveil plugin to any img tag on the page. The -400 in there tells unveil to only "unveil" the real image after it's 400 or more pixels into the viewport. If you specify no value here at all the image is unveiled precisely when it gets into the viewport, and this is normally what you'll want, but for this sample I wanted you to see the placeholder images a little better.

OK go ahead and open up the html file in your favorite browser! Depending on your monitor resolution, you might either see just the word "hi!", or maybe you'll see a blue circle or 2 at the bottom of your screen. Now scroll down slowly. You'll see the blue circles come up on screen, and if you keep scrolling they turn into other images (the final destination images as denoted by data-src). Pretty nifty huh? Feel free to play around with that -400, change it to other values to see the change in behavior. The closer you get to 0, the less time (vertical scroll-wise) you'll have to see the blue placeholder circles. The more negative the number gets, the longer you see the blue placeholders.

If you get truly excited by all this, you can bring up the developer tools of your favorite browser (mostly by hitting the F12 key) and watching the timing of image downloads to confirm you're getting what you think you're seeing.



What's Next?

There are other lazy loading JS image libraries out there, including some that are JQuery plugins. Play around with them and see if you find another you like. I like this one because it's extremely light-weight and easy to use, but maybe you'll find one you like better.

You could also create your own sample page from scratch. That's the best way to learn after all, not by copying something another person has already done.

Resources

unveil
JQuery

No comments:

Post a Comment