LazyLoad

LazyLoad is a plugin that allows you to defer image loading until the image is scrolled to.

Download Debut Article Example Usage

Plugin Code (Version 2.1)

var LazyLoad = new Class({

	Implements: [Options,Events],

	/* additional options */
	options: {
		range: 200,
		elements: "img",
		container: window,
		mode: "vertical",
		realSrcAttribute: "data-src",
		useFade: true
	},

	/* initialize */
	initialize: function(options) {
		
		// Set the class options
		this.setOptions(options);
		
		// Elementize items passed in
		this.container = document.id(this.options.container);
		this.elements = document.id(this.container == window ? document.body : this.container).getElements(this.options.elements);
		
		// Set a variable for the "highest" value this has been
		this.largestPosition = 0;
		
		// Figure out which axis to check out
		var axis = (this.options.mode == "vertical" ? "y": "x");
		
		// Calculate the offset
		var offset = (this.container != document.body && this.container != document.body ? this.container : "");

		// Find elements remember and hold on to
		this.elements = this.elements.filter(function(el) {
			// Make opacity 0 if fadeIn should be done
			if(this.options.useFade) el.setStyle("opacity", 0);
			// Get the image position
			var elPos = el.getPosition(offset)[axis];
			// If the element position is within range, load it
			if(elPos < this.container.getSize()[axis] + this.options.range) {
				this.loadImage(el);
				return false;
			}
			return true;
		},this);
		
		// Create the action function that will run on each scroll until all images are loaded
		var action = function(e) {
			
			// Get the current position
			var cpos = this.container.getScroll()[axis];
			
			// If the current position is higher than the last highest
			if(cpos > this.largestPosition) {
				
				// Filter elements again
				this.elements = this.elements.filter(function(el) {
					
					// If the element is within range...
					if((cpos + this.options.range + this.container.getSize()[axis]) >= el.getPosition(offset)[axis]) {
						
						// Load the image!
						this.loadImage(el);
						return false;
					}
					return true;
					
				},this);
				
				// Update the "highest" position
				this.largestPosition = cpos;
			}
			
			// relay the class" scroll event
			this.fireEvent("scroll");
			
			// If there are no elements left, remove the action event and fire complete
			if(!this.elements.length) {
				this.container.removeEvent("scroll", action);
				this.fireEvent("complete");
			}
			
		}.bind(this);
		
		// Add scroll listener
		this.container.addEvent("scroll", action);
	},
	loadImage: function(image) {
		// Set load event for fadeIn
		if(this.options.useFade) {
			image.addEvent("load", function(){
				image.fade(1);
			});
		}
		// Set the SRC
		image.set("src", image.get(this.options.realSrcAttribute));
		// Fire the image load event
		this.fireEvent("load", [image]);
	}
});

/* usage */
window.addEvent('domready',function() {
	var lazyloader = new LazyLoad();
});

Options and Events

Options for LazyLoad include:

  • range: (defaults to 200) The amount of space from the container’s bottom position that you want to look for images to load.
  • image: (defaults to “blank.gif”) The image to replace the original image.
  • resetDimensions: (defaults to true) Removes the image’s width and height attributes.
  • elements: (defaults to “img”) Images to consider for lazy loading.
  • container: (defaults to window) The container for which to look for images within.
  • mode: (defaults to “vertical”) The mode for which the plugin will adjust to.

Events for LazyLoad include:

  • Complete: Fires when all images have been loaded.
  • Load: Fires on each individual image once it has been loaded.
  • Scroll: Fires when the container is scrolled.

Code Revisions & Bug Fixes

None.

Comments

  1. Hey David, I am using your Side Scroll plugin, and I was wondering what I need to change for this to work with scrolling sideways. Thanks for your help :)

  2. @Boris: I needed the same behaviour as you and implemented it: http://gist.github.com/255921

  3. @thomasd: I edited the original and switched the ‘Y’ with ‘X’ and it seems to work. Besides the ability to switch between modes did you do the same thing?

  4. Yes making an option for switching from ‘x’ to ‘y’ was all that was needed.

  5. Thanks David,

    once more a neat and highly usable plugin – good work as usual ;)

    cheers
    Frank

  6. Gregor July 11, 2010

    It looks like in GChrome images were loaded at once all of them -> Example usage

  7. @Gregor: WebKit doesn’t respect LazyLoading. No way no how.

  8. Did you really remove the comments pointing out that the routine does not work anymore with modern browsers (including FF4)? That’s really weak! So you’d rather have people use a script that does nothing as it should? Use HttpFox and see for yourself!

    • I’ve not deleted any comments. I’ll have a look at this. Thanks for reporting this so kindly.

    • This worked for me in FF4, BTW. WebKit doesn’t allow unobtrusive lazyload. What issue are you having? DId you clear cache?

    • I have discovered the root issue. I’ll be releasing LazyLoad 2.0 this weekend.

  9. Hey david,
    I have lots of images to load on my website, and not all of them has data-src, so they they wont load. it replaces nothing in src and then its just viewing broken image. (for example of images that dont have data-src: icons on the comments, post thumbnail etc.)

    Can you add something to the class that will check if theres and data-src, if there is – ONLY then it will use lazyload for the img?

    Thanks alot,
    Elron

  10. I think there is a typo in your 2.1 release. Line 32: should have ‘this.container != window’ instead of a repeat of ‘this.container != document.body’

  11. on my website (one of many) I’ve got pictures in many formats floating left.
    problem:
    If i create static container img.lazy {width:150px; height:100px} for example, and image i wish to show got w=300;h=450 then it’s a)scaled to 150×100 b)cropped to 150×100.
    question:
    is there a chance to morph/resize container div to image real size?

    and now something completely different:
    i wish google to index my images and wish to use lazyload. only solution i’ve got is to server side checking user-agent string/searching ip in google bots ip list and create different version of site for them. is there any other way?
    something like:

    window.addEvent('domready',function() {
    $$('img.lazy').addEvent(' _BEFORE_LOAD_ ', function(e){e.stop();}
    var lazyloader = new LazyLoad();
    });

  12. i work around something like:
    window.addEvent('domready',function() {
    $$('img.lazy').each(function(el){
    el.set('data-src',el.get('src'));
    el.set('src','');
    });
    var lazyloader = new LazyLoad();

    but there is problem: min-width:150px;min-height:150px – i got”boxex” for images, but most of them is visible at start, so lazyload start doing his job. first pic got for example 800×600, 2nd 520x 730 and soon. lazyload try to load every image witch “visible box”, so it still try to load 20-30 images in same time even if third pic will not be visible at all after firs two shows up. i don’t know what to do with it. any suggestions?

  13. Could you make this work for touch scroll also?

  14. Does this code separately arranged for each page. I’m confused a little bit of inexperience. I intend to use my own photos would be helpful. Do I need to use if this so crowded?

  15. uncaught referenceerror class is not defined.

  16. […] with, it also means we need to maintain existing code.  With Firefox 4's release came news that my MooTools LazyLoad plugin was not intercepting image loading — the images were loading regardless of the plugin, much like […]

  17. 初到贵博客,体验不错,希望博主多多分享好的内容,也欢迎博主加入博客互推联盟,多多跟其他博友互动。

Be Heard

Tip: Wrap your code in <pre> tags or link to a GitHub Gist!

Use Code Editor