hostmonster-Host Unlimited Domains on 1 Account   coolhandle offering reliable webhosting since 2001
Unlimited Hosting Space - FREE Site Builder   Smart Website Solutions for Your Small Business=

Redefining Lazy Loading With Lazy Load XT

Redefining Lazy Loading With Lazy Load XT

Lazy loading is a common software design pattern that defers the initialization of objects until they are needed. Lazy loading images started to become popular on the web back in 2007, when Mika Tuupola drew inspiration from the YUI ImageLoader utility and released a jQuery plugin1. Since then, it’s become a popular technique to optimize page loading and the user experience. In this article I will discuss why we should and shouldn’t use Lazy Load, and how to implement it.

Why Lazy Load?

Images make up over 60% of an average page’s size, according to HTTP Archive2. Images on a web page would be rendered once they are available. Without lazy loading, this could lead to a lot of data traffic that is not immediately necessary (such as images outside of the viewport) and longer waiting times. The problem? Visitors are not patient at all. By lazy loading, images outside of the viewport are loaded only when they would be visible to the user, thus saving valuable data and time.

Lazy loading is not limited to images. It can be used on pages with complex JavaScript, iframes and third-party widgets, delaying the loading of these resources until the user actually needs them.

Why Not Lazy Load?

Lazy loading is not a silver bullet, and it is known to affect performance. For example, most lazy-loading implementations either don’t have a src attribute in the img tags (which is invalid syntax, according to the HTML5 standard) or point to a blank image (hello, spacer.gif). This approach requires duplicate img tags wrapped in noscript tags for browsers with JavaScript disabled (or with the NoScript plugin installed):

img data-src="path" attributes /noscriptimg src="path" attributes //noscript

Fortunately, this duplication doesn’t increase the page’s size significantly when you enable Gzip compression. However, some search engines might not index your images correctly, because the noscript tag is not indexed within content, and the img tag outside of noscript is referring to a blank image. Currently, Google seems to eventually index lazy-loaded images, but other search engines are less likely to.

How Is Lazy Loading Implemented?

You might be overwhelmed by the number of lazy-load plugins out there. You might also think that implementing one is easy: Just monitor page scrolling (or resizing), and then set the src attribute when an image is visible. If only it were that easy. Many things come into play when building a solid solution that works on both desktop and mobile. So, how do you separate the signal from the noise?

  • Throttling
    Checking the visibility of images after every interaction (even a tiny bit of scrolling) could compromise the page’s responsiveness. To ease that, implement some sort of throttling mechanism.
  • All your mobile are belong to us
    There is no scroll event in the Opera Mini browser and some old feature phones. If you receive traffic from those devices, you should monitor and load all images directly.
  • Lazy load or automatic pagination?
    Some implementations check only whether an image is above the fold. If the page is scrolled down to the very bottom via an anchor (or the scrollTo method in JavaScript), then all images below the fold will begin to download, instead of only the images within the viewport. This is more a matter of automatic pagination because users will have to wait for the remaining images to load after an interaction.
  • Dynamic image insertion
    Many websites use AJAX navigation nowadays. This requires a lazy-load plugin to support the dynamic insertion of images. To prevent a memory leak, any references to images that are not in the DOM (for example, ones that appear after an AJAX-based replacement of content) should also be removed automatically.

This list is certainly not comprehensive. We have many more issues to consider, such as the lack of getBoundingClientRect in old browsers, a change in orientation without an ensuing resize event on the iPhone, or the particular handling requirements of the jQuery Mobile framework.

Unfortunately, most plugins do not handle all of the above.

Lazy Load XT

We’ve been optimizing web performance on numerous screens for almost a decade now. Our project Mobile Joomla3 has been applied to over a quarter billion web pages and is still one of the most popular ways to optimize Joomla websites for mobile. Thanks to this, we’ve been lucky to witness the evolution of the web from desktop to mobile and observe trends and changing needs.

With our latest project, RESS.io4, we’ve been working on an easy solution to automatically improve responsive design performance on all devices. Lazy loading became an integral part of the project, but we came to realize that current lazy-load implementations are insufficient for the growing needs of the modern web. After all, it’s not just about desktop, mobile and images anymore, but is more and more about other media as well, especially video (oh, and did I hear someone say “social media widgets”?).

We concluded that the modern web could use a mobile-oriented, fast, extensible and jQuery-based solution. That is why we developed one and called it Lazy Load XT315.

Here are its main principles, which consider both current and future applications:

  • It should support jQuery Mobile6 out of the box.
  • It should support the jQuery7, Zepto8 and DOMtastic9 libraries. Of course, writing the solution in native JavaScript is possible, but jQuery is a rather common JavaScript extension nowadays, and one of our aims was to simplify the transition from the original Lazy Load to Lazy Load XT. This makes jQuery an adequate choice. However, if you don’t want to use jQuery at all, read the “Requirements” section below for details on reducing the size of dependent libraries.
  • It must be easy to start. The default settings should work most of the time. Prepare the HTML, include the JavaScript, et voilà!

Include

Lazy Load XT requires jQuery 1.7+, Zepto 1.0+ or DOMtastic 0.7.2+. Including the plugin is easy and as expected:

script src="jquery.min.js"/script
script src="jquery.lazyloadxt.min.js"/script

script$.lazyLoadXT.extend({edgeY: 200});/script

styleimg.lazy {display:none}/style

Use

By default, the plugin processes all images on the page and obtains an image’s actual source path from the data-src attribute. So, the recommended snippet to place an image on the page is this:

img class="lazy" data-src="path" [attributes] /noscriptimg src="path" [attributes] //noscript

From this snippet, it is clear why we’ve set img.lazy above to display: none: Hiding the image is necessary in case there is no JavaScript, or else both the original image and the placeholder would be displayed. If the src attribute of the img tag is not set, then the plugin will set it to be a transparent GIF using the data-uri attribute.

If you’re not worried about users who have disabled JavaScript (or about valid HTML5 code), then just load jquery.lazyloadxt.min.js and replace the src attribute in the images with data-src:

script src="jquery.min.js"/script
script src="jquery.lazyloadxt.min.js"/script
img data-src="path" [attributes] /

Video

Lazy Load XT is available in two versions: jquery.lazyloadxt.js and jquery.lazyloadxt.extra.js. The latter includes better support of video elements, both video tags and ones embedded in iframe (such as YouTube and Vimeo).

Markup changes are similar to the above, and replacing the src attributes with data-src and post with data-poster is sufficient if you’re using them in a video element.

script src="jquery.lazyloadxt.extra.js"/script
iframe data-src="//www.youtube.com/embed/[videocode]?rel=0" width="320" height="240"/iframe
video data-poster="/path/to/poster.jpg" width="320" height="240" controls
   source data-src="/path/to/video.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
   source data-src="/path/to/video.ogv" type='video/ogg; codecs="theora, vorbis"'
/video
video data-src="/path/to/video2.mp4" width="320" height="240" controls

Size

The size of the jquery.lazyloadxt.min.js file is 2.3 KB (or 1.3 KB Gzip’ed), and the size of jquery.lazyloadxt.extra.min.js is 2.7 KB (or 1.4 KB Gzip’ed). That’s small enough, especially compared to jQuery and Zepto.

Requirements

Even though Lazy Load XT requires jQuery, Zepto or DOMtastic, loading the full versions of any of them is not necessary. For example, DOMtastic requires only a minimal set of modules (gulp --include=attr, class, data, event, selector, type) for you to get a 7.9 KB file (or 2.7 KB Gzip’ed), bringing the total size of both DOMtastic and Lazy Load XT to just 4 KB (Gzip’ed).

Compatibility

We’ve tested Lazy Load XT in the following browsers:

  • Internet Explorer 6 – 11
  • Chrome 1 – 37
  • Firefox 1.5 – 32.0
  • Safari 3 – 7
  • Opera 10.6 – 24.0
  • iOS 5 – 7 (stock browsers)
  • Android 2.3 – 4.4 (stock browsers)
  • Amazon Kindle Fire 2 and HD 8.9 (stock browsers)
  • Opera Mini 7

Performance

We have tested Lazy Load XT’s performance on a page with one thousand images and are happy with the results: Scrolling works well even on old Android 2.3 devices.

We also successfully tested various iterations of Lazy Load XT on over one thousand websites for several months in our jQuery Mobile-based Elegance and Flat templates10.

Options

The plugin’s default settings may be modified with the $.lazyLoadXT object:

$.lazyLoadXT.edgeY = 200;
$.lazyLoadXT.srcAttr = 'data-src';

Note that you may change this object at any time: before loading the plugin, between loading and when the document is ready, and after the event is ready. (Note that the last option doesn’t affect initialized images.)

Lazy Load XT supports a lot of options and events, enabling you to integrate other plugins or implement new features. For the full list and details, see Lazy Load XT’s GitHub page11.

AJAX Support

If you use jQuery Mobile with built-in AJAX page loading, then the Lazy Load XT plugin will do all of the magic for you in the pageshow event. In general, you should run the code below to initialize images inside a container with AJAX-loaded content.

$(window).lazyLoadXT();

Or run this:

$('#ajaxContainer').lazyLoadXT();

Extending Lazy Load XT

Lazy Load XT can be extended easily using the oninit, onshow, onload and onerror handlers or the related lazyinit, lazyshow, lazyload and lazyerror events. In this way, you can create amazing add-ons.

Some examples can be found on the GitHub page12, along with usage instructions13. We’ll highlight just a few of them here.

Loading Animation

Customizing the image-loading animation is easy. By default, Lazy Load XT includes spinner14 and fade-in15 animations, but you can use any effects from the Animate.css16 project or any other.

Responsive Images

Lazy Load XT has two add-ons for responsive images17. One is “srcset,” to polyfill the srcset attribute (and that should be renamed data-srcset):

img data-srcset="image-hd.jpg 2x, image-phone.jpg 360w, image-phone-hd.jpg 360w 2x"

The second is “picture,” a polyfill for the picture tag:

picture width="640" height="480"
   br data-src="small320.jpg"
   br media="(min-width: 321px)" data-src="medium480.jpg"
   br media="(min-width: 481px)" data-src="large640.jpg"
   noscriptimg data-src="large640.jpg"/noscript
   pImage caption/p
/picture

Page Widgets

Lazy Load XT makes it possible to lazy-load page widgets18 (such as Facebook, Twitter or whatever widget you like). Insert any HTML code in the page using the “widget” add-on when an element becomes visible. Wrap the code in an HTML comment inside of a div with an ID attribute, and give the element a data-lazy-widget attribute with the value of that ID:

!-- Google +1 Button --
div data-lazy-widget="gplus" class="g-plusone" data-annotation="inline" data-width="300"/div
div id="gplus" !--
   
   (function() {
      var po = document.createElement('script'),
      s = document.getElementsByTagName('script')[0];
      po.type = 'text/javascript'; po.async = true;
      po.src = 'https://apis.google.com/js/platform.js';
      s.parentNode.insertBefore(po, s);
   })();
   
--/div

If the data-lazy-widget attribute has an empty value, then the element itself will be used as a wrapper:

div data-lazy-widget!--
   
--/div

Many other add-ons are available, too. They include infinite scrolling, support for background images, loading all images before displaying them (if the browser supports it), and deferring the autoloading of all images.

Is There A Silver Bullet?

Lazy loading images is not a standard browser feature today. Also, no third-party browser extensions exist for such functionality.

One might assume that the lazyload attribute in the “Resource Priorities19” draft specification by Microsoft and Google would do it. However, it has another purpose: to set the background priority for a corresponding resource element (image, video, script, etc.). Thus, if your aim is to load JavaScript or CSS before images, that’s your choice. There is another killer attribute, postpone, which prevents any resource from loading until you set the CSS display property to a value other than none. The good news is that support for the lazyload attribute is in Internet Explorer 11. The bad news is that the postpone attribute has not been implemented yet.

We do not know when or if the draft specification above will ever be fully supported by the major browsers. So, let’s look at the solutions we have now.

Some people have attempted to solve the duplication of the img tag in noscript tags by keeping only the noscript part and processing it with JavaScript. Unfortunately, noscript has no content in Internet Explorer, and it is not included in the DOM at all in Android’s stock browser (other browsers may behave similarly).

An alternative would be to use the /code tag, instead of noscript, like so:

scriptfunction Z(){document.write('br ');}/script
scriptZ();/scriptimg src="path" attributes /

So, img would be an attribute of the br tag and would transform br tags into img data-src at the document.ready event. But this method requires document.write and is not compatible with AJAX-based navigation. We have implemented this method in the script add-on for Lazy Load XT, but the standard way using data-attributes seems to be clearer.

Finally, Mobify has an elegant Capturing API20 (see the recent review on Smashing Magazine21) that transforms HTML into plain text using the following code and then processes it with JavaScript:

document.write('plaintext style="display:none"');

Unfortunately, this solution has drawbacks of its own: It is quite slow, and the browser might treat it as a JavaScript-based HTML parser. Also, combining this solution with AJAX navigation is not clear, and it is not guaranteed to work correctly in all browsers because the plaintext tag was deprecated in HTML 2. It actually doesn’t work in W3C’s Amaya browser and on some feature phones (such as Nokia E70). Nevertheless, these are edge cases, and you may use Mobify.js and Lazy Load XT simultaneously, although that is beyond the scope of this article.

Comparing Lazy Load Solutions

Both Lazy Load XT and the original Lazy Load are not the only solutions around. Below we compare most of the major existing solutions:

Conclusion

The total size of media elements on the average web page is increasing constantly. Yet, especially on mobile devices, performance bottlenecks remain, which stem from bandwidth issues, widely varying network latency, and limitations on memory and the CPU. We need solutions for better and faster browsing experiences that work across all devices and browsers.

While no single lazy-load standard exists so far, we welcome you to try Lazy Load XT, especially if lazy-loaded video or other media is an important part of your website’s functionality.

Download and Contribute

Bug reports, patches and feature requests are welcome.

(al, ml)

Footnotes

  1. 1 http://www.appelsiini.net/projects/lazyload
  2. 2 http://httparchive.org/interesting.php
  3. 3 http://www.mobilejoomla.com/
  4. 4 http://ress.io/
  5. 5 https://github.com/ressio/lazy-load-xt
  6. 6 http://jquerymobile.com/
  7. 7 http://jquery.com/
  8. 8 http://zeptojs.com/
  9. 9 http://webpro.github.io/DOMtastic/
  10. 10 http://www.mobilejoomla.com/templates.html
  11. 11 https://github.com/ressio/lazy-load-xt#options”
  12. 12 http://ressio.github.io/lazy-load-xt
  13. 13 https://github.com/ressio/lazy-load-xt/#extendability
  14. 14 https://github.com/ressio/lazy-load-xt/#spinner
  15. 15 https://github.com/ressio/lazy-load-xt/#fade-in-animation
  16. 16 https://github.com/daneden/animate.css
  17. 17 https://github.com/ressio/lazy-load-xt/#responsive-images
  18. 18 https://github.com/ressio/lazy-load-xt/#widgets
  19. 19 https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/ResourcePriorities/Overview.html
  20. 20 https://hacks.mozilla.org/2013/03/capturing-improving-performance-of-the-adaptive-web/
  21. 21 http://www.smashingmagazine.com/2013/10/24/automate-your-responsive-images-with-mobify-js/
  22. 22 http://www.appelsiini.net/projects/lazyload
  23. 23 http://ressio.github.io/lazy-load-xt/
  24. 24 http://luis-almeida.github.io/unveil/
  25. 25 http://jquery.eisbehr.de/lazy/
  26. 26 https://github.com/jetmartin/responsive-lazy-loader
  27. 27 http://dinbror.dk/blazy/
  28. 28 http://vvo.github.io/lazyload/
  29. 29 http://toddmotto.com/echo-js-simple-javascript-image-lazy-loading/
  30. 30 http://ressio.github.io/lazy-load-xt/
  31. 31 https://github.com/ressio/lazy-load-xt
  32. 32 https://raw.github.com/ressio/lazy-load-xt/master/dist/jquery.lazyloadxt.min.js
  33. 33 https://raw.github.com/ressio/lazy-load-xt/master/dist/jquery.lazyloadxt.extra.min.js
  34. 34 http://ressio.github.io/lazy-load-xt/demo/

↑ Back to topTweet itShare on Facebook

Article source: http://www.smashingmagazine.com/2015/02/03/redefining-lazy-loading-with-lazy-load-xt/

Tags:


Submit a Review




If you want a picture to show with your review, go get a Gravatar.

1&1 has shared hosting and dedicated hosting solutions for every budget and free domains with all hosting packages!  StartLogic - Affordable hosting: Free setup/domain, unlimited emails, PHP, mySQL, CGI, FrontPage. As low as $3.95/month
Cloud ecommerce platform delivers more traffic, higher conversion and unmatched performance

© Copyright 2008 Tyconia International, Inc. All Rights Reserved.