tuupola/lazyload

Multi-serve fluid images based on width break-points?

efdeevee opened this issue · 9 comments

I'm trying to track image widths and change the contents of data_attribute in order to serve the best possible size.

So far I have the following condensed code which adds a data-display attribute containing the correct data on resize.

The new attribute is added and changes correctly, but unfortunately I can't get lazyload to listen to the new data.

Bit new with jQuery I'm afraid, could this be on the right track at all?

// Markup
<img data-large="image-1024.jpg" data-medium="image-512.jpg" data-small="image-256.jpg" height="4000" src="blank.gif" width="3000">

// Script
function loadImages() {
    $( 'img' ).each( function() {
        var $image = $( this );
        var $imageAttribute = 'data-display';
        var $imageWidth = $image.width();
        if( $imageWidth > 512 )
            $image.attr( $imageAttribute, $image.data( 'large' ) );
        else if( $imageWidth > 256 )
            $image.attr( $imageAttribute, $image.data( 'medium' ) );
        else
            $image.attr( $imageAttribute, $image.data( 'small' ) );
        }
    } ).lazyload( {
        data_attribute: 'display'
    } );
}
$( document ).on( 'ready', loadImages );
$( window ).on( 'resize', loadImages );

// Style
img {
    height: auto;
    max-width: 100%;
}

URL of the page you have problems with?

Created a condensed version at http://jsfiddle.net/efdeevee/WETGD/ to show what I'm trying to do.

The CSS for img widths is set to 256, 512 and 1024. The script adds/updates a data-display attribute on load/resize, which contains the data taken from the data-large, data-medium and data-small attributes.

On load seems to work, but I'm not sure how to have lazyload listen to resize changes in order to serve the best image size.

Is it at all possible?

Thank you for looking!

I think it is because jQuery caches the value of $.data() calls. You could try to change lines

https://github.com/tuupola/jquery_lazyload/blob/master/jquery.lazyload.js#L105

var original = $self.data(settings.data_attribute);

to

var original = $self.attr("data-" + settings.data_attribute);

https://github.com/tuupola/jquery_lazyload/blob/master/jquery.lazyload.js#L127

.attr("src", $self.data(settings.data_attribute));

to

.attr("src", $self.attr("data-" + settings.data_attribute));

To see if that causes the problem in your case.

It does the trick! Along with your modification suggestions above, I ended up using the following which now includes a device ratio check as well.

function loadImages() {
    $( 'img' ).each( function() {
        var $image = $( this );
        var $imageAttribute = 'data-original';
        var $imageWidth = $image.width();
        var $pixelRatio = window.devicePixelRatio;
        if( $imageWidth > 256 && $pixelRatio > 1 || $imageWidth > 512 )
            $image.attr( $imageAttribute, $image.data( 'large' ) );
        else if( $imageWidth > 0 && $pixelRatio > 1 || $imageWidth > 256 )
            $image.attr( $imageAttribute, $image.data( 'medium' ) );
        else
            $image.attr( $imageAttribute, $image.data( 'small' ) );
    } ).lazyload();
}
$( document ).on( 'ready', loadImages );
$( window ).on( 'resize', loadImages );

I hope it could be of use to someone else.

Ok thanks! I probably change $.data() to use $.attr("data-" + xxx) instead.

Good news, thanks again.

Related to #101

Update.

Although the benefits of serving multiple dimensions might be obvious, I'm finding the above a bit expensive on memory when displaying multiple images on a page. Especially Firefox seems to become less responsive, probably because of the amount of cached alternative sizes.

Still searching for a more stable solution to make things lighter somehow. I recall reading an issue here suggesting to unload things when it's moved out of the viewport, perhaps worth exploring...

Fixed in 1.9.x.