Giter Site home page Giter Site logo

afarkas / lazysizes Goto Github PK

View Code? Open in Web Editor NEW
17.3K 284.0 1.7K 2.84 MB

High performance and SEO friendly lazy loader for images (responsive and normal), iframes and more, that detects any visibility changes triggered through user interaction, CSS or JavaScript without configuration.

License: MIT License

JavaScript 59.84% HTML 35.57% CSS 4.59%
javascript lazyload lazy-evaluation lazysizes responsive-images performance

lazysizes's Introduction

lazysizes

lazysizes is a fast (jank-free), SEO-friendly and self-initializing lazyloader for images (including responsive images picture/srcset), iframes, scripts/widgets and much more. It also prioritizes resources by differentiating between crucial in view and near view elements to make perceived performance even faster.

It may become also your number one tool to integrate responsive images. It can automatically calculate the sizes attribute for your responsive images, it allows you to share media queries for your media attributes with your CSS, helping to separate layout (CSS) from content/structure (HTML) and it makes integrating responsive images into any environment really simple. It also includes a set of optional plugins to further extend its functionality.

How to

  1. Download the lazysizes.min.js script and include lazysizes in your webpage. (Or install via npm: npm install lazysizes --save or bower bower install lazysizes --save)

    <script src="lazysizes.min.js" async=""></script>

    Or:

    import 'lazysizes';
    // import a plugin
    import 'lazysizes/plugins/parent-fit/ls.parent-fit';
    
    // Note: Never import/require the *.min.js files from the npm package.

    Note: For more information see here.

  2. lazysizes does not need any JS configuration: Add the class "lazyload" to your images/iframes in conjunction with a data-src and/or data-srcset attribute. Optionally you can also add a src attribute with a low quality image:

    <!-- non-responsive: -->
    <img data-src="image.jpg" class="lazyload" />
    <!-- responsive example with automatic sizes calculation: -->
    <img
        data-sizes="auto"
        data-src="image2.jpg"
        data-srcset="image1.jpg 300w,
        image2.jpg 600w,
        image3.jpg 900w" class="lazyload" />
    <!-- iframe example -->
    <iframe frameborder="0"
    	class="lazyload"
        allowfullscreen=""
        data-src="//www.youtube.com/embed/ZfV-aYdU4uE">
    </iframe>

Can be seen here

Responsive image support (picture and/or srcset)

Lazysizes is built upon the Responsive image standard and extends it with additional functionality. For full cross browser responsive image support you must use either a full polyfill like picturefill or use the extreme lightweight partial respimg polyfill plugin or the responsive image on demand plugin. Alternatively, you can simply define a fallback src via the data-src attribute. If you want to learn more about the responsive image syntax read "The anatomy of responsive images".

What makes lazysizes so awesome:

lazysizes is different than other lazy image loaders.

  1. Detects any visibility changes on current and future lazyload elements in any web environment automatically: The script works as an universal, self-initializing, self-configuring and self-destroying component and detects any changes to the visibility of any current and future image/iframe elements automatically no matter whether it becomes visible through a user scroll, a CSS animation triggered through :hover or through any kind of JS behavior (carousel, slider, infinite scroll, masonry, isotope/filtering/sorting, AJAX, SPAs...). It also works automatically in conjunction with any kind of JS-/CSS-/Frontend-Framework (jQuery mobile, Bootstrap, Backbone, Angular, React, Ember (see also the attrchange/re-initialization extension)).
  2. Future-proof: It directly includes standard responsive image support (picture and srcset)
  3. Separation of concerns: For responsive image support it adds an automatic sizes calculation as also alias names for media queries feature. There is also no JS change needed if you add a scrollable container with CSS (overflow: auto) or create a mega menu containing images.
  4. Performance: It's based on highly efficient, best practice code (runtime and network) to work jank-free at 60fps and can be used with hundreds of images/iframes on CSS and JS-heavy pages or webapps.
  5. Extendable: It provides JS and CSS hooks to extend lazysizes with any kind of lazy loading, lazy instantiation, in view callbacks or effects (see also the available plugins/snippets).
  6. Intelligent prefetch/Intelligent resource prioritization: lazysizes prefetches/preloads near the view assets to improve user experience, but only while the browser network is idling (see also expand, expFactor and loadMode options). This way in view elements are loaded faster and near of view images are preloaded lazily before they come into view.
  7. Lightweight, but mature solution: lazysizes has the right balance between a lightweight and a fast, reliable solution
  8. SEO improved: lazysizes does not hide images/assets from Google. No matter what markup pattern you use. Google doesn't scroll/interact with your website. lazysizes detects, whether the user agent is capable to scroll and if not, reveals all images instantly.

More about the API

lazysizes comes with a simple markup and JS API. Normally you will only need to use the markup API.

Markup API

Add the class lazyload to all img and iframe elements, which should be loaded lazy. Instead of a src or srcset attribute use a data-src or data-srcset attribute:

<img data-src="image.jpg" class="lazyload" />
<!-- retina optimized image: -->
<img data-srcset="responsive-image1.jpg 1x, responsive-image2.jpg 2x" class="lazyload" />

Automatically setting the sizes attribute

lazysizes supports setting the sizes attribute automatically, corresponding to the current size of your image - just set the value of data-sizes to auto.

<img
	data-sizes="auto"
	data-srcset="responsive-image1.jpg 300w,
	    responsive-image2.jpg 600w,
	    responsive-image3.jpg 900w"
    class="lazyload" />

Important: How sizes is calculated: The automatic sizes calculation uses the display width of the image. This means that the width of the image has to be calculable at least approximately before the image itself is loaded (This means you can not use width: auto). Often the following general CSS rule might help: img[data-sizes="auto"] { display: block; width: 100%; } (see also specifying image/iframe dimensions with the recommended aspect ratio definition). If it is below 40 (can be configured through the minSize option), lazysizes traverses up the DOM tree until it finds a parent which is over 40 and uses this number.

The width auto-calculated by lazysizes can be modified using the lazybeforesizes event (lazybeforesizes documentation). Alternatively, the parent fit plugin can be used for sizing images to fit a parent / container, and is the only solution when an image's height needs to be taken into account when fitting it to its container (This also includes the use of object-fit).

The data-sizes="auto" feature only makes sense if you use the data-srcset attribute with width descriptors which allows the most appropriate image can be selected (It does not make sense if you use the x descriptor or only src.).

Recommended/possible markup patterns

lazysizes allows you to write an endless variety of different markup patterns. Find your own/best pattern or choose one of the following. (All of the following patterns can be also used for art direction using the picture element.)

Simple pattern

Add the class lazyload and simply omit the src attribute or add a data uri as fallback src.

<!--  responsive adaptive example -->

<img
	class="lazyload"
	data-srcset="image.jpg 1x, image2.jpg 2x"
    alt="my image" />
<!--  retina optimized example -->
<img class="lazyload"
	data-srcset="progressive-image.jpg 1x, progressive-image2.jpg 2x"
    alt="my image" />

<!-- or non-responsive: -->
<img
	data-src="image.jpg"
	class="lazyload" />

Note: In case you are using either srcset/data-srcset or picture, we recommend to extend this pattern with either a data-src (see next pattern: "Combine data-srcset with data-src") or with a suitable src attribute (see: "modern pattern" or "LQIP").

Combine data-srcset with data-src

In case you want to use responsive images for supporting browsers, but don't want to include a polyfill, simply combine your data-srcset with a data-src attribute.

<!-- responsive example: -->
<img
	data-sizes="auto"
    data-src="image3.jpg"
	data-srcset="image3.jpg 600w,
	    image1.jpg 220w,
	    image2.jpg 300w,
	    image3.jpg 600w,
	    image4.jpg 900w"
	class="lazyload" />

Note: Due to the fact that the data-src will also be picked up by "Read-Later" Apps and other tools (for example Pin it button), this pattern also makes sense if you use a polyfill. In case you don't use a polyfill it is recommended that the first image candidate matches the fallback src.

LQIP/blurry image placeholder/Blur up image technique

If you are using the LQIP (Low Quality Image Placeholder) pattern, simply add a low quality image as the src:

<!-- responsive example: -->
<img
	data-sizes="auto"
    src="lqip-src.jpg"
	data-srcset="lqip-src.jpg 220w,
    image2.jpg 300w,
    image3.jpg 600w,
    image4.jpg 900w" class="lazyload" />

<!-- or non-responsive: -->
<img src="lqip-src.jpg" data-src="image.jpg" class="lazyload" />

The LQIP technique can be enhanced by combining it with CSS transitions/animation to sharpen/unblur or overfade the LQIP image.

Please also have a look at our lazysizes Blur Up plugin (recommended).

<style>
	.blur-up {
		-webkit-filter: blur(5px);
		filter: blur(5px);
		transition: filter 400ms, -webkit-filter 400ms;
	}

	.blur-up.lazyloaded {
		-webkit-filter: blur(0);
		filter: blur(0);
	}
</style>

<img src="lqip-src.jpg" data-src="image.jpg" class="lazyload blur-up" />

<!-- ... -->

<style>
	.fade-box .lazyload,
	 .fade-box .lazyloading {
		opacity: 0;
		transition: opacity 400ms;
	}

	.fade-box img.lazyloaded {
		opacity: 1;
	}
</style>

<div class="ratio-box fade-box">
	<img src="lqip-src.jpg" />
	<img data-src="image.jpg" class="lazyload" />
</div>

modern transparent srcset pattern

Combine a normal src attribute with a transparent or low quality image as srcset value and a data-srcset attribute. This way modern browsers will lazy load without loading the src attribute and all others will simply fallback to the initial src attribute (without lazyload). (This nice pattern originated from @ivopetkov.)

<img
    src="image3.jpg"
    srcset="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
	data-srcset="image3.jpg 600w,
		image1.jpg 220w,
	    image2.jpg 300w,
	    image4.jpg 900w"
	data-sizes="auto"
	class="lazyload" />

The noscript pattern

In case disabled JavaScript is a concern you can combine this simple pattern with an image inside a noscript element.

<style>
	.no-js img.lazyload {
    	display: none;
    }
</style>

<!-- noscript pattern -->
<noscript>
	<img src="image.jpg" />
</noscript>
<img src="transparent.jpg" data-src="image.jpg" class="lazyload" />

Note: As an alternative to the noscript pattern also checkout the noscript extension.

[data-expand] attribute

Normally lazysizes will expand the viewport area to lazy preload images/iframes which might become visible soon. This value can be adjusted using the expand option.

Additionally, this general option can be overridden with the data-expand attribute for each element. Different than the general expand option the data-expand attribute also accepts negative values (All numbers but 0 are accepted!).

This becomes especially handy to add unveiling effects for teasers or other elements:

<style>
.lazyload,
.lazyloading {
	opacity: 0;
}
.lazyloaded {
	opacity: 1;
	transition: opacity 300ms;
}
</style>

<div class="teaser lazyload" data-expand="-20">
    <img data-src="image.jpg" class="lazyload" />
    <h1>Teaser Title</h1>
    <p>...</p>
</div>

CSS API

lazysizes adds the class lazyloading while the images are loading and the class lazyloaded as soon as the image is loaded. This can be used to add unveil effects:

/* fade image in after load */
.lazyload,
.lazyloading {
	opacity: 0;
}
.lazyloaded {
	opacity: 1;
	transition: opacity 300ms;
}
/* fade image in while loading and show a spinner as background image (good for progressive images) */

.lazyload {
	opacity: 0;
}

.lazyloading {
	opacity: 1;
	transition: opacity 300ms;
	background: #f7f7f7 url(loader.gif) no-repeat center;
}

Broken image symbol

In case you are using an alt attribute but do not declare a src/srcset attribute you will end up with a broken image symbol.

There are two easy ways to deal with it.

Either define a src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" or add the following CSS.

img.lazyload:not([src]) {
	visibility: hidden;
}

JS API

lazysizes automatically detects new elements with the class lazyload so you won't need to call or configure anything in most situations.

JS API - options

Options can be set by declaring a global configuration option object named lazySizesConfig. This object must be defined before the lazysizes script. A basic example:

window.lazySizesConfig = window.lazySizesConfig || {};

// use .lazy instead of .lazyload
window.lazySizesConfig.lazyClass = 'lazy';

// use data-original instead of data-src
lazySizesConfig.srcAttr = 'data-original';

//page is optimized for fast onload event
lazySizesConfig.loadMode = 1;

In case you are using a module bundler it is recommended to change the options directly after importing the lazysizes module:

import lazySizes from 'lazysizes';
// other imports ...

lazySizes.cfg.lazyClass = 'lazy';

Here the list of options:

  • lazySizesConfig.lazyClass (default: "lazyload"): Marker class for all elements which should be lazy loaded (There can be only one class. In case you need to add some other element, without the defined class, simply add it per JS: $('.lazy-others').addClass('lazyload');)
  • lazySizesConfig.preloadAfterLoad (default: false): Whether lazysizes should load all elements after the window onload event. Note: lazySizes will then still download those not-in-view images inside of a lazy queue, so that other downloads after onload are not blocked.)
  • lazySizesConfig.preloadClass (default: "lazypreload"): Marker class for elements which should be lazy pre-loaded after onload. Those elements will be even preloaded, if the preloadAfterLoad option is set to false. Note: This class can be also dynamically set ($currentSlide.next().find('.lazyload').addClass('lazypreload');).
  • lazySizesConfig.loadingClass (default: "lazyloading"): This class will be added to img element as soon as image loading starts. Can be used to add unveil effects.
  • lazySizesConfig.loadedClass (default: "lazyloaded"): This class will be added to any element as soon as the image is loaded or the image comes into view. Can be used to add unveil effects or to apply styles.
  • lazySizesConfig.expand (default: 370-500): The expand option expands the calculated visual viewport area in all directions, so that elements can be loaded before they become visible. The default value is calculated depending on the viewport size of the device. (Note: Reasonable values are between 300 and 1000 (depending on the expFactor option.) In case you have a lot of small images or you are using the LQIP pattern you can lower the value, in case you have larger images set it to a higher value. Also note, that lazySizes will dynamically shrink this value to 0 if the browser is currently downloading and expand it if the browser network is currently idling and the user not scrolling (by multiplying the expand option with 1.5 (expFactor)). This option can also be overridden with the [data-expand] attribute.
  • lazySizesConfig.minSize (default: 40): For data-sizes="auto" feature. The minimum size of an image that is used to calculate the sizes attribute. In case it is under minSize the script traverses up the DOM tree until it finds a parent that is over minSize.
  • lazySizesConfig.srcAttr (default: "data-src"): The attribute, which should be transformed to src.
  • lazySizesConfig.srcsetAttr (default: "data-srcset"): The attribute, which should be transformed to srcset.
  • lazySizesConfig.sizesAttr (default: "data-sizes"): The attribute, which should be transformed to sizes. Makes almost only makes sense with the value "auto". Otherwise, the sizes attribute should be used directly.
  • lazySizesConfig.customMedia (default: {}): The customMedia option object is an alias map for different media queries. It can be used to separate/centralize your multiple specific media queries implementation (layout) from the source[media] attribute (content/structure) by creating labeled media queries. (See also the custommedia extension).
  • lazySizesConfig.loadHidden (default: true): Whether to load visibility: hidden elements. Important: lazySizes will load hidden images always delayed. If you want them to be loaded as fast as possible you can use opacity: 0.001 but never visibility: hidden or opacity: 0.
  • lazySizesConfig.ricTimeout (default: 0): The timeout option used for the requestIdleCallback. Reasonable values between: 0, 100 - 1000. (Values below 50 disable the requestIdleCallback feature.)
  • lazySizesConfig.throttleDelay (default: 125): The timeout option used to throttle all listeners. Reasonable values between: 66 - 200.
<script>
window.lazySizesConfig = window.lazySizesConfig || {};
window.lazySizesConfig.customMedia = {
    '--small': '(max-width: 480px)',
    '--medium': '(max-width: 900px)',
    '--large': '(max-width: 1400px)',
};
</script>


<picture>
	<!--[if IE 9]><video style="display: none;><![endif]-->
	<source
		data-srcset="http://placehold.it/500x600/11e87f/fff"
		media="--small" />
	<source
		data-srcset="http://placehold.it/700x300"
		media="--medium" />
	<source
		data-srcset="http://placehold.it/1400x600/e8117f/fff"
		media="--large" />
	<source
        data-srcset="http://placehold.it/1800x900/117fe8/fff" />
    <!--[if IE 9]></video><![endif]-->
    <img

        data-src="http://placehold.it/1400x600/e8117f/fff"
        class="lazyload"
        alt="image with artdirection" />
</picture>
  • lazySizesConfig.expFactor (default: 1.5): The expFactor is used to calculate the "preload expand", by multiplying the normal expand with the expFactor which is used to preload assets while the browser is idling (no important network traffic and no scrolling). (Reasonable values are between 1.5 and 4 depending on the expand option).
  • lazySizesConfig.hFac (default: 0.8): The hFac (horizontal factor) modifies the horizontal expand by multiplying the expand value with the hFac value. Use case: In case of carousels there is often the wish to make the horizontal expand narrower than the normal vertical expand option. Reasonable values are between 0.4 - 1. In the unlikely case of a horizontal scrolling website also 1 - 1.5.
  • lazySizesConfig.loadMode (default: 2): The loadMode can be used to constrain the allowed loading mode. Possible values are 0 = don't load anything, 1 = only load visible elements, 2 = load also very near view elements (expand option) and 3 = load also not so near view elements (expand * expFactor option). This value is automatically set to 3 after onload. Change this value to 1 if you (also) optimize for the onload event or change it to 3 if your onload event is already heavily delayed.
  • lazySizesConfig.init (default: true): By default lazysizes initializes itself, to load in view assets as soon as possible. In the unlikely case you need to setup/configure something with a later script you can set this option to false and call lazySizes.init(); later explicitly.

JS API - events

lazysizes provides three events to modify or extend the behavior of lazysizes.

  • lazybeforeunveil: This event will be fired on each lazyload element right before of the "unveil" transformation. This event can be used to extend the unveil functionality. In case the event is defaultPrevented the default transformation action will be prevented (see also the ls.unveilhooks.js plugin):
//add simple support for background images:
document.addEventListener('lazybeforeunveil', function(e){
    var bg = e.target.getAttribute('data-bg');
    if(bg){
        e.target.style.backgroundImage = 'url(' + bg + ')';
    }
});
//or add AJAX loading
//<div class="lazyload" data-ajax="my-url.html"></div>

$(document).on('lazybeforeunveil', function(){
	var ajax = $(e.target).data('ajax');
    if(ajax){
        $(e.target).load(ajax);
    }
});

The lazybeforeunveil can also be used for lazy initialization and due to the fact that lazysizes also detects new elements in the DOM automatically also for auto- and self-initialization of UI widgets:

<script>
document.addEventListener('lazybeforeunveil', function(e){
    $(e.target)
        .filter('.slider')
        .slider({
            sliderOption: true
        })
    ;
});

document.addEventListener('lazybeforeunveil', function(e){
    $(e.target)
        .filter('.chart')
        .chart({
            animate: true
        })
    ;
});
</script>

<div class="slider lazyload lazypreload"></div>

<div class="chart lazyload" data-expand="-10"></div>
  • lazyloaded: After the image is fully loaded lazysizes dispatches a lazyloaded event. While this often duplicates the native load event it is often more convenient to use.

  • lazybeforesizes: This event will be fired on each element with the data-sizes="auto" attribute right before the calculated sizes attribute will be set. The event.detail.width property is set to the calculated width of the element and can be changed to any number. In case the event is defaultPrevented the sizes attribute won't be set. See also the parent-fit extension.

$(document).on('lazybeforesizes', function(e){
    //use width of parent node instead of the image width itself
    e.detail.width = $(e.target).parents(':not(picture)').innerWidth() || e.detail.width;
});

JS API - methods

lazySizes.loader.unveil(DOMNode)

In case a developer wants to show an image even if it is not inside the viewport the lazySizes.loader.unveil(DOMNode) can be called:

lazySizes.loader.unveil(imgElem);

Note: As a more lazy alternative the lazypreload class can be set: $(imgElem).addClass('lazypreload');.

lazySizes.autoSizer.checkElems()

In case one or more image elements with the attribute data-sizes="auto" have changed in size lazySizes.autoSizer.updateElems can be called (For example to implement element queries):

lazySizes.autoSizer.checkElems();
lazySizes.loader.checkElems()

Tests whether new elements has came into view. Normally this method only needs to be called, if lazySizesConfig.loadMode was set to 0.

lazySizes.init()

LazySizes initializes itself automatically. In case you set lazySizesConfig.init to false you need to explicitly call lazySizes.init(). Note: You can speed up initial loading of in view images if you call lazySizesConfig.init() explicitly after lazysizes and all plugins are loaded.

<script>
window.lazySizesConfig = window.lazySizesConfig || {};
window.lazySizesConfig.init = false;
</script>

<script src="lazysizes.js"></script>
<script src="other-script.js"></script>
<script>
lazySizes.init();
</script>

Browser Support

lazysizes supports all browsers, that support document.getElementsByClassName (== all browsers but not IE8-). In case you need to support IE8, see also the noscript extension (or use a modified noscript pattern or the LQIP pattern).

Contributing

Fixes, PRs and issues are always welcome, make sure to create a new branch from the master (not the gh-pages branch), validate against JSHint and test in all browsers. In case of an API/documentation change make sure to also document it here in the readme.md.

Build

Run npx grunt to validate JSHint and uglify/minify all files.

Tests

Run npx serverino -p 3333 and navigate to http://localhost:3333/tests/

Available plugins in this repo

It is recommended to concat all plugins together with lazySizes. In case you don't concat it is recommended to include the plugin scripts before the lazySizes main script.

The respimg polyfill plugin is an extremely lightweight alternate polyfill for the most important subsets of responsive images (srcset and picture).

The srcset attribute with the w descriptor and sizes attribute automatically also includes high DPI images. But each image has a different optimal pixel density, which might be lower (for example 1.5x) than the pixel density of your device (2x or 3x). This information is unknown to the browser and therefore can't be optimized for. The lazySizes optimumx extension gives you more control to trade between perceived quality vs. perceived performance.

The parent fit plugin extends the data-sizes="auto" feature to also calculate the right sizes for object-fit: contain|cover image elements and other height ( and width) constrained image elements in general.

The object fit polyfill plugin polyfills the object-fit and the object-position property in non supporting browsers.

The blur up / effect plugin allows you to create great over fade / blur up effects with low quality image placeholder, which improves the user experience and perceived performance in case you are using a low quality image approach.

attrchange / re-initialization extension (strongly recommended if you use React, Angular etc.)

In case you are changing the data-src/data-srcset attributes of already transformed lazyload elements, you must normally also re-add the lazyload class to the element.

This attrchange / re-initialization extension automatically detects changes to your data-* attributes and adds the class for you.

The artdirect plugin allows you to fully control art direction via CSS.

There are also other plugins/extension in the plugins folder. As always you are open to create new ones for your project.

Tip: Specifying image dimensions (minimizing reflows and avoiding page jumps)

To minimize reflows, content jumping or unpredictable behavior with some other JS widgets (isotope, masonry, some sliders/carousels...) the width and the height of an image should be calculable by the browser before the image source itself is loaded:

<img

    style="width: 350px; height: 150px;"
	data-srcset="http://placehold.it/350x150 1x,
    http://placehold.it/700x300 2x"
    data-src="http://placehold.it/350x150"
    class="lazyload" />

For flexible responsive images the CSS intrinsic ratio scaling technique should be used:

<style>
.ratio-container {
    position: relative;
}
.ratio-container:after {
    content: '';
    display: block;
    height: 0;
    width: 100%;
    /* 16:9 = 56.25% = calc(9 / 16 * 100%) */
    padding-bottom: 42.86%;
}
.ratio-container > * {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: block;
}
</style>

<div class="ratio-container">
    <img

        data-sizes="auto"
        data-srcset="http://placehold.it/175x75 175w,
        http://placehold.it/350x150 350w,
        http://placehold.it/700x300 700w,
        http://placehold.it/1400x600 1400w"
        data-src="http://placehold.it/700x300"
        class="lazyload" />
</div>

In case you want to dynamically calculate your intrinsic ratios for many different formats you can vary the pattern to something like this:

<style>
.ratio-box {
	position: relative;
	height: 0;
	display: block;
	width: 100%;
	/* padding-bottom is calculated and rendered in to HTML */
}

.ratio-box img,
.ratio-box iframe,
.ratio-box video {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	display: block;
}
</style>

<div class="ratio-box" style="padding-bottom: 42.85% /* calc(75 / 175 * 100%)*/;">
    <img

        data-sizes="auto"
        data-srcset="http://placehold.it/175x75 175w,
        http://placehold.it/350x150 350w,
        http://placehold.it/700x300 700w,
        http://placehold.it/1400x600 1400w"
        data-src="http://placehold.it/700x300"
        class="lazyload" />
</div>

In case the exact ratio of your image is unknown you can also vary the intrinsic ratio like this:

<style>
.ratio-container {
    position: relative;
}
.ratio-container:after {
    content: '';
    display: block;
    height: 0;
    width: 100%;
    /* 16:9 = 56.25% = calc(9 / 16 * 100%) */
    padding-bottom: 56.25%;
    content: "";
}
.ratio-container > * {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

/* unknown ration variation */
.unknown-ratio-container > * {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
}
</style>

<div class="ratio-container unknown-ratio-container">
    <img

        data-src="http://placehold.it/350x150"
        class="lazyload" />
</div>

or at least add a min-height (and min-width) to minimize content jumps:

.lazyload,
.lazyloading {
	min-height: 200px;
}

Note:

  • If you use the "unknown intrinsic ratio pattern" and the width of the loaded image will not (approximately) match the width of its container, the data-sizes="auto" feature will not be effective when used on its own. In this situation, the most appropriate size for the image to fit in the available space can be calculated automatically using the parent fit plugin.

Updating layout of JS widgets

In case you can't specify the image dimensions using CSS or one of the above suggested methods and your JS widgets have problems to calculate the right dimensions. You can use the following pattern to update your JS widgets (sliders/masonry):

$('.my-widget').each(function(){
    var $module = $(this);
    var update = function(){
        $module.myWidget('updateLayout');
    };

    // Note: Instead of waiting for all images until we initialize the widget
    // we use event capturing to update the widget's layout progressively.
    this.addEventListener('load', update, true);

    $module.myWidget();
});

For this update pattern you may want to combine this at least with the min-height pattern explained above.

Tip: Where/How to include lazySizes

While lazy loading is a great feature, it is important for users that crucial in view images are loaded as fast as possible. (Most users start to interact with a page after in view images are loaded.)

In case you normally combine all your scripts into one large script and add this to the bottom of your page, it can be better for perceived performance to generate two or sometimes more script packages: One small package, which includes all scripts which have heavy influence on the content or the UI and another larger one which includes the normal behavior of the page.

This smaller script, which should include lazySizes (and all its plugins), should then be placed before any other blocking elements (i.e.: script(s)) at the end of the body or after any blocking elements (i.e.: scripts, stylesheets) in the head to load the crucial content as fast possible. (Note: It might make also sense to call lazySizes.init(); explicitly right after lazySizes and all its plugins are added.)

Why lazysizes

In the past, I often struggled using lazy image loaders, because the "main check function" is called repeatedly and with a high frequency. Which makes it hard to fulfill two purposes runtime and memory efficiency. And looking into the source code of most so called lazy loaders often also unveils lazy developers...

But in a world of responsive retina optimized images on the one hand and JS widgets like carousels or tabs (a lot of initially hidden images) on the other hand lazy loading images becomes more and more important, so I created this project.

lazysizes is different:

Due to the fact, that it is designed to be invoked with a high frequency and therefore works highly efficient, it was possible to hook into all kinds of events as a mutationobserver meaning this lazyloader works as a simple drop in solution - you simply write/render your markup and no matter whether the .lazyload element was added by AJAX or revealed by a JS or CSS animation it will be picked up by lazysizes.

<!-- responsive example: -->
<img
	data-sizes="auto"

	data-srcset="image2.jpg 300w,
    image3.jpg 600w,
    image4.jpg 900w"
    data-src="image3.jpg"
    class="lazyload" />

<!-- or non-responsive: -->
<img
    data-src="image.jpg"
    class="lazyload" />

lazysizes's People

Contributors

afarkas avatar baedda avatar bordeo avatar christina-grannas avatar christopherdarling avatar coliff avatar dahmian avatar dependabot[bot] avatar grekko avatar hecktarzuli avatar hokamoto avatar j-smit avatar joeyquarters avatar jschroeter avatar kbav avatar kkirsche avatar krille avatar lrancez avatar michaeldhopkins avatar mortonfox avatar muratcorlu avatar neatonk avatar orkon avatar oskarrough avatar prayagverma avatar suisho avatar tikotzky avatar undistraction avatar yannbertrand avatar ysugimoto avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lazysizes's Issues

Filesize: Move script loading and "preloadAfterLoad" into plugins

I would like to improve extensibility of lazysizes, while keeping it small. I think I can/should therefore move the script loading as also the preloadAfterLoad option into a plugin/snippet to keep everything as small as possible.

In case someone things otherwise, please speak up ;).

see also:
#17

At the same time the plugin/snippet folder should be imrpoved with documentation.

What about responsive + retina images?

I mean we can set or
data-srcset="lqip-src.jpg 100w, image2.jpg 300w"
or
data-srcset="lqip-src.jpg 1x, image2.jpg 2x"

Is there a way to add both in same srcset? For ex
data-srcset="lqip-src.jpg 100w 1x, lqip-src_2x.jpg 100w 2x, image2.jpg 300w 1x, image2_2x.jpg 300w 2x"

Or is there any other way to set responsive retina ready images?
PS: Thanks for nice plugin !

Lazy loading on iPad

Hi!
It seem like Apple introduced scroll events even when using inertial scrolling (Although still not as frequenst as one would like).
I think you could use this to make images load during scroll, instead of when scroll has come to a complete stop, for iOS 8 devices.

What do you think?

Thank you for a great script!

Prevent upscaling when using data-sizes="auto"

<img
    data-sizes="auto"
    src="lqip-src.jpg"
    data-srcset="lqip-src.jpg 220w,
    image2.jpg 300w,
    image3.jpg 600w,
    image4.jpg 900w" class="lazyload" />

E.g. when the image will be shown at a width of 320px, lazysizes will set sizes="320px". Great. But now the browser/polyfill chooses the 300px image and upscales it to 320px. The result is a blurry image.
Wouldn't it be better, if lazysizes would (maybe via a config parameter) set sizes="600px" in this case? Of course this will result in more data to be transferred, but downscaling usually looks much better than upscaling.

Can't get bgset to work

This has been a really useful script for lazyloading individual background images via unveilhooks, but I can't seem to get the bgset plugin to work at all. In Chrome it seems to load at least one image, but doesn't switch out when the viewport changes. It doesn't request the images at all in Firefox or Safari.

I've tried it locally with picturefill, rias, and respimage, but none of them seem to do the trick.

Am I missing something really simple?

Link here:
http://codepen.io/TPDBrendan/pen/azyYKx

LQIP issue on Chrome

Hey there,

I'm facing a strange issue in Chrome (both Win and Mac, v39 and v40 tested) when trying to specify a dummy image (just to preserve height avoid repaints on a fluid layout) as LQIP src.

I'm using a srcset to specify 2x image for the browsers that support it and here's the markup:

<img class="lazyload" src="dummy.png" data-src="image.png" srcset="" data-srcset="[email protected] 2x"> 

With the src="dummy.png" specified, src attribute value never gets swapped in Chrome, while everything perfectly works when src="". All other browsers seem to be fine.

Here's a real world example:
http://doxie.tigran.io/info/awards.html

P.S. to be reproduced on a non-retina display.

force load hidden images

in a project i have images in hidden tabs(`div``s), so they are not rendered (b'cose of display:none)
how can i force them to load?

Support for Background Images

Your data-sizes="auto" feature is brilliant. Would it be possible to support background images too? For example, if I set a background image to 100%, the resolutions required for mobile vs desktop vary greatly.

CSS variables could be used in the stylesheets to specify multiple images: http://www.broken-links.com/2014/08/28/css-variables-updating-custom-properties-javascript/

body {
background: url(img/low-quality.jpg);
--data-src: url(img/high-quality.jpg);
}

Of course things get complicated with multiple background images. If a srcset is used instead, replacements can be logically applied by matching the low quality image in the srcset to the other declarations.

body {
background: url(img/low-quality.jpg), url(img/overlay.jpg);
--data-srcset: url(img/low-quality.jpg), url(img/high-quality.jpg);
}

In this case, the background's url(img/low-quality.jpg) should become lazysized. The overlay image should remain unchanged.

Prevent init not working

And I guess it's because this:
if(lazySizesDefaults.init){ setTimeout(init);
``}

Should be:
if(lazySizesConfig.init){ setTimeout(init);
``}

Correct?

Sizes being computed from height

Is height a variable in the computation of the sizes attribute? I've got a slider where lazysizes is setting the sizes attribute at the height of the slider, rather than it's width, which returns a stretched low-resolution image... is this proper behavior?

Browser support

First of all, congrats for this plugin, work like a charm

I have a question about browser support.

You said that this browser are supported:

lazysizes supports the following browsers: IE9+, Firefox 21+, Chrome 27+, Safari 6.1+, iOS Safari 7.0+, Android 4.1+

With polifill / respimg or without this?

Transform "beforeUnveil" and "beforeSizes" callbacks to event

Currently any system can hook into the "get in view logic" and extend changing the sizesor "unveiling" elements through the beforeUnveil or beforeSizes callback for something like a background or a video poster it could look something like this:

lazySizesConfig = {
    beforeUnveil: function(element){
        var tmpAttribute = element.getAttribute('data-bg');

        //handle background image
        if( tmpAttribute ) {
            element.style.backgroundImage = tmpAttribute;
            return false;
        }

        //handle poster
        tmpAttribute = element.getAttribute('data-poster');

        if(tmpAttribute){
            element.poster = tmpAttribute;

            //handle preload
            if(element.preload == 'none'){
                element.preload = 'auto';
            }
            return false;
        }
    }
};

For seperation of concerns it would be a lot better to handle does extendable cases through events. The beforeUnveil option could be called beforeunveil, lazyinview or ?. The beforeSizes callback could be called beforesizes, lazyautosizesor ?. Any suggestions are appreciated!!!

Using this system could be used with and without event delegation:

Here an example using event delegation for the backgroundImage transition and for the video[data-poster] transition:

//add simple support for background images:
document.addEventLister('beforeunveil', function(e){
    var bg = e.target.getAttribute('data-bg');
    if(bg){
        e.target.style.backgroundImage = bg;
        e.preventDefault();
    }
}, true);

//add simple support for video elements
document.addEventListener('beforeunveil', function(e){
    var poster = this.getAttribute('data-poster');
    if(poster){
        this.poster = poster;
        if(this.preload == 'none'){
            this.preload = 'auto';
        }
        e.preventDefault();
    }
});

This way lazySizes handles still the most important usecases (image, iframes) and is lightweight, but makes sure that other usecases can be implemented much easier.

Note: backgroundimages and video posters are not scanned by the preload parser. Therefore they delay the onload event, but aren't often delaying other resources (because thier download priority is already often lower, that from other resources).

see also: #2 and #1

Missing examples of iframes/scripts

The description says: "iframes and scripts/widgets without any dependency," but there aren't any examples of iframes or scripts being loaded. Do you have something like that you could add to the README?

This looks really good, and my use case is potentially asynchronously loading banner ads (like Google) responsively.

how would loading this widget work out?

the lack of a clear data-src in these scripts, I'm wondering can these widgets be lazy loaded using this lib and how so? or a direction to get there...

<a class="twitter-timeline"  href="https://twitter.com/AZEALIABANKS" data-widget-
id="558162421052112896">Tweets by @AZEALIABANKS</a>

<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:
/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+":
//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
</script>

OR

<div id="fb-root"></div>
<script>(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&appId=619160344859792&version=v2.0";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>

<div class="fb-activity" data-site="developers.facebook.com" data-action="likes, recommends"
 data-colorscheme="light" data-header="true"></div>

thank you.

Updatesize if parent don't have size

First of all, thank you for this very nice script.

I've recently stumbled upon a small issue. I had my images inside of links, but these links hadn't "display block" set on them, causing them to not have any width set. This prevent the data-sizes="auto" from working correctly. Although it's easy to fix on my side (set a width on my links), I was wondering if it wouldn't be interesting that the script looks into the hierarchy until it finds a node with a valid width?

Need help from wordpress/php developer for a lazySizes wordpress plugin

I started a simple wordpress plugin to bring lazySizes to wordpress. While this plugin already works great, I'm clearly not a php developer nor a wordpress plugin author and would like to hand this project over to someone more capable doing this.

One big goal is to work seamlessly with the following responsive images plugin (and maybe others):
https://wordpress.org/support/plugin/ricg-responsive-images

In total I don't expect too much work for a php dev (should stay simple).

So in case you are one or you know someone, let me know.

Same with, different height. Should chose specified image ratio

Hi,

if we have this case, when image has w=300px and h=400px (3:4 ratio)

f1dca95552daa788b7975d333d788f53

and this case, same width, w=300px but different height h=169px (16:9 ratio)
staticshot_19-01-2015_18-52-46

In wordpress we generate all sizes of this image, so in src-set will be this both ratios, with same width. We use css intrinsic ratio scaling technique. But we can't figure it out to load what image (image ratio) should be loaded. Is anything that I miss? Maybe should add some extra parameter data-ratio?

Thanks.

Worth it?

No really an issue, more a thought/question.. because browsers are catching up with implementations and have short release cycles these days.. is it worth to implement such a script/feature into a site when on the browser side things are moving so fast you might not need this, only if you want super browser support and performance is a high priority. (simply put)

As a reference also read (but you probably already know this):
http://css-tricks.com/responsive-images-youre-just-changing-resolutions-use-srcset/

Thoughts? I like this though, don't get me wrong.

lazy load on background-image

Hello,

What I'm tryin to do is loading some element


and its empty and lets say, after this on click for example
$(".load").click(function(){
$(".sliceImg").css({
backgroundImage: 'url(pictures/pic.jpg)'
}).attr("data-bg", "newPic.jpg");
});

And it's doesnt work, it is loading new background-image but set data-bg (on inspector element) but script does not change background for better quality.

Is there anything so I can update script after click ? or make it working?

Thank you :)

Error handler prevents Integration with other Libs

Hi,
first of all great lib!
I have integrated it with a compont library of us and found that it breaks the following functionality or our component:
It renders out the tag and registeres a handler for the error event which fires when the resource given in the src property cannot be loaded.
In that case the component updates it via the data-src indirection.
Problem is that lazysizes seems to override the error handler on this line:
https://github.com/aFarkas/lazysizes/blob/gh-pages/lazysizes.js#L32
I don't even see a reason for that.
I see two solutions:

1.) Don't override the error handler
2.) provider something like data-fallbacl-src an handle it accordingly

Is possible to notify lazysizes that the data-src was updated?

Hi,

First of all, thanks for a great library!

In my case I dynamically update the URL of the image being shown. I use Ember.JS so there is a binding where I bind the src property of my component to data-src attribute. The src property may change and therefore whenever it happens the data-src is updated as well. But the change is not picked up by the lazysizes - i.e., the first time shown image remains in the src attribute forever.

Is it possible to notify lazysizes about the update?

A workaround for me would be either re-render the entire component or to set the src attribute manually. In the latter case I would loose the lazysizes' features after the src update (such as plugins or lazy load).

Best regards,
Alex

How does this work with SPAs?

Will this script work in the following situation:

  • single page app
  • a modal displays a content rendered from a template which includes images that become visible only as the user scrolls the content of the modal (which is bigger than the modal's height)

This could apply to a remotely loaded HTML block but the difference is that with a remotely HTML you know when the block is injected and you might trigger a reinitialization of the script while with a SPA it's more complicated.

respimage & lazysizes & IE8?

Hi there,

First tests look promising, thanks for this!
On one of my projects, I switched from picturefill to your respimage polyfill in combination with this lazysizes plugin. Since respimage supports IE8 and lazysizes doesn't, I'm running into the following problem:

I have a flexslider setup with responsive <picture> elements inside of it. The first picture is loaded normally in the DOM, the rest has the lazyload class like this:

<div class="flexslider">
  <ul class="slides">
    <li class="landscape">
      <picture id="img-0">
        <!--[if IE 9]><video style="display: none;"><![endif]-->
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-07-2-1024x668.jpg 1x" media="(min-width:510px)">   
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-07-2-480x313.jpg 1x">
        <!--[if IE 9]></video><![endif]-->
        <img srcset="http://mydomain.com/media/my-image-07-2-1024x668.jpg" alt="my alt text" />
      </picture>
    </li>
    <li class="landscape">
      <picture id="img-1">
        <!--[if IE 9]><video style="display: none;"><![endif]-->
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-07-1024x668.jpg 1x" media="(min-width:510px)">     
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-07-480x313.jpg 1x">
        <!--[if IE 9]></video><![endif]--> 
        <img data-sizes="auto"
        src="http://mydomain.com/media/my-image-07-480x313.jpg"
        data-srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-07-1024x668.jpg 1x"
        alt="my alt text"
        class="lazyload" />
      </picture>
    </li>
    <li class="landscape">
      <picture id="img-2">
      <!--[if IE 9]><video style="display: none;"><![endif]-->
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-06-1024x682.jpg 1x" media="(min-width:510px)"> 
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-06-480x319.jpg 1x">
        <!--[if IE 9]></video><![endif]-->
        <img
        data-sizes="auto"
        src="http://mydomain.com/media/my-image-06-480x319.jpg"
        data-srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-06-1024x682.jpg 1x"
        alt="my alt text"
        class="lazyload" />
      </picture>
    </li>
    <li class="landscape">
      <picture id="img-3">
      <!--[if IE 9]><video style="display: none;"><![endif]-->
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-04-1024x682.jpg 1x" media="(min-width:510px)"> 
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-04-480x319.jpg 1x">
        <!--[if IE 9]></video><![endif]--> 
        <img
        data-sizes="auto"
        src="http://mydomain.com/media/my-image-04-480x319.jpg"
        data-srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-04-1024x682.jpg 1x"
        alt="my alt text"
        class="lazyload" />
      </picture>
    </li>
    <li class="landscape">
      <picture id="img-4">
        <!--[if IE 9]><video style="display: none;"><![endif]-->
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-02-1024x682.jpg 1x" media="(min-width:510px)"> 
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-02-480x319.jpg 1x">
        <!--[if IE 9]></video><![endif]--> 
        <img
        data-sizes="auto"
        src="http://mydomain.com/media/my-image-02-480x319.jpg"
        data-srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-02-1024x682.jpg 1x"
        alt="my alt text"
        class="lazyload" />
      </picture>
    </li>
    <li class="landscape">
      <picture id="img-5">
        <!--[if IE 9]><video style="display: none;"><![endif]-->
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-05-1024x682.jpg 1x" media="(min-width:510px)"> 
        <source srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-05-480x319.jpg 1x">
        <!--[if IE 9]></video><![endif]--> 
        <img
        data-sizes="auto"
        src="http://mydomain.com/media/my-image-05-480x319.jpg"
        data-srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-05-1024x682.jpg 1x"
        alt="my alt text"
        class="lazyload" />
      </picture>
    </li>
    <li class="portrait">
      <picture id="img-6">
        <!--[if IE 9]><video style="display: none;"><![endif]--> <source
        srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-03-444x682.jpg 1x" media="(min-width:510px)"> <source
        srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-03-480x735.jpg 1x"> <!--[if IE 9]></video><![endif]-->
        <img
        data-sizes="auto"
        src="http://mydomain.com/media/my-image-03-480x735.jpg"
        data-srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-03-444x682.jpg 1x"
        alt="my alt text"
        class="lazyload" />
      </picture>
    </li>
  </ul>
</div>

This works great except for the fact that some browsers will load the fallback src in the img first, but that's something I can live with.

The problem however is that from slide 2 and up, IE8 will only show the (lowres) fallback src and that's too low of quality for desktop screens. Off course I can increase the quality of the fallback image, but then the other browsers will download these heavier fallback images too...

I tried using a conditional statement for IE8 instead of the fallback src like this:

<img data-sizes="auto"
data-srcset="http://mydomain.com/media/[email protected] 2x, http://mydomain.com/media/my-image-07-1024x668.jpg 1x"
alt="my alt text"
class="lazyload" />
<!--[if lte IE 8]><img src="http://mydomain.com/media/my-image-07-480x313.jpg" alt="my alt text" /><![endif]-->

but that results in an empty image container with just the alt text with the conditional image underneath it.

Is there a easy workaround for this?
Thanks a lot!

lazysizes and progressive image rendering

Alexander, thanks for sharing this great script, it works like a charm! We're looking for a solution for dynamic sizes for a long time.

I just stumbled upon one thing: when using the LQIP pattern, browsers (tested Chrome and FF) skip their nice Progressive JPG rendering. That means, the low quality image will stay visible until the high quality image is completely loaded. But actually at one (unknown) point during loading the high quality image, the progressive rendering would be better than the low quality version. I found a similar issue about browsers skipping progressive rendering when the src attribute is being replaced, this also seems to happen when browsers switch from src to srcset. Removing the src attribute before setting a new value/srcset helps. But of course the image would be gone for a few seconds.

I just prototyped a little hack which places the low quality src as background image on lazybeforeunveil and removes the src attribute. It seems to work well, have a look:

  1. Image: original lazysizes with LQIP pattern
  2. Image: lazysizes with LQIP pattern + background image hack
  3. Image: native srcset with fixed sizes

Chrome: http://www.webpagetest.org/video/view.php?id=150118_d352f41d3adc756fe1334948b8f692aa693f079e
Firefox: http://www.webpagetest.org/video/view.php?id=150118_191a1951405f6c8e68a9c6695bd36544962adb46

Or try in your browser: http://schroetermedien.de/_temp/respo/

What do you think? Does this make sense? I mean actually this is something the browsers could fix, but I guess they won't fix it. It works well in our case with the low quality src, but e.g. imagine when replacing a 2x image with a 3x variant, rendering the new src progressively would cause a short unwanted loss of quality.

Thanks a lot,
Jakob

Settings

Another "issue"/feature request is that as it is right now, you need to apply the settings before you add the script source, otherwise it will self initialize before you have the change to set init to false.
You have a 0 delay on the init itself if I'm not mistaken, men then it's to late. What about also wrap the init check in that delay? It messes up my structure that I have to put it in a special order instead in order to remove the auto init. Not a big deal, but might be worth thinking about.
Otherwise everything works great! Thanks!

Interchanging menus?

Hi,

is it possible to interchange also complete div constructions with lazysizes? I want to put out a mega menu for desktop and a different menu for mobile. Different html, so that can't be solved by a normal responsive menu. I don't want to load both menus and just hide one by css. Is that possible and what is the best practice?

Thanks!

Detect image sizes in callback/ loaded event

Trying to detect portrait images by checking loaded images sizes...

As i know i can use only one lazybeforesizes event for it, but looks like it fires to early (lazybeforeunveil fires even earlier).

function checkPortrait(el) {
        var imgWidth = el.clientWidth,
            imgHeight = el.clientHeight;
       console.log(imgWidth);
        console.log(imgHeight);
        if (imgWidth < imgHeight) {
            alert('Ta-da, portrait detected!');
        }
}

    document.addEventListener('lazybeforesizes', function(e) {
        checkPortrait(e.target);
    }, false);

it doesn't work and in console i got 0 sizes ((

how can win this challenge? ))
tnx

srcset on safari

Hi!

I have a strange issue on safari (latest version)

There is a strange data-risrc and data-risrcset that is added and the image is not displaying. I've been looking at your code but I don't see any function that does this...

Sample html below:

<img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" 
data-srcset="/assets/SetWidth320213-Screen-Shot-2015-01-13-at-15.40.30.png 320w,
/assets/SetWidth640426-Screen-Shot-2015-01-13-at-15.40.30.png 640w,
/assets/SetWidth960639-Screen-Shot-2015-01-13-at-15.40.30.png 960w,
/assets/SetWidth1280852-Screen-Shot-2015-01-13-at-15.40.30.png 1280w" 
data-sizes="auto" alt="Screen Shot 2015 01 13 at 15.40.30" 
class=" lazyloaded lazyautosizes" sizes="293px" 
srcset="" 
data-risrc="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" 
data-risrcset="/assets/SetWidth320213-Screen-Shot-2015-01-13-at-15.40.30.png 320w,/assets/SetWidth640426-Screen-Shot-2015-01-13-at-15.40.30.png 640w,
/assets/SetWidth960639-Screen-Shot-2015-01-13-at-15.40.30.png 960w,
/assets/SetWidth1280852-Screen-Shot-2015-01-13-at-15.40.30.png 1280w" width="293" style="">

Dynamic Update with RIAS does not work in FF 35.0.1

Hi,

In FF, the lib gives the src attribute a value that was not processed by the rias plugin. So the steps to reproduce the problem are like these:

  1. Dynamically assign the following values to the img element: data-absurl="false", data-sizes="120px", data-widths:"[180,320,640,960]", src:"/imgs/img_{width}.png"
  2. Add the lazyload class to the img element.

Expected: img.src === src:"/imgs/img_180.png"
Actual: img.src === src:"/imgs/img_{width}.png"

I've tried to trace the issue and this lead me to the updatePolyfill function (line 74). In FF it's executed and it sets the wrong src (as far as I see). In Chrome, this line isn't executed.

Best regards,
Alex

Request: Looks great, what about background images?

I would love to use this, however a lot of the designs that I do deal with large, full screen, background images for each "scene" on a webpage as the user scrolls down the page. Would your script be able to work with this? I know I could place the image in with position: absolute and lay the content over it, but it seems like there is more room for error here. Using background images with background-size: cover seems to work better for me.

data-srcset with filenames containing spaces breaks parsing

When using filenames that contain whitespace (which may easily occur when customers upload files with unexpected filenames) parsing of data-srcset breaks.

E.g. data-srcset="http://localhost/uploads/images/test (1).jpg 320w, http://localhost/uploads/images/test (1).jpg 480w"

-> 'Failed parsing 'srcset' attribute value since it has an unknown descriptor.'

LQIP technique using css background images

Hi,

first of all, congratulations for this awesome plugin! Very nice work.
I would like to ask you if is possible to use LQIP technique while using background images instead of img tags. For now, I'm using jQuery Cover plugin (https://github.com/greenish/jquery-cover), but it would be great to have this feature out of the box. The advantage of using background images with css is that you can have cover mode support without additional scripts.

Thanks
Hugo

Won't pass W3C Markup Validation

Hi there,

I'm using your superb plugin in a flexslider to only load the first (responsive) image and lazyload the rest with the following (recommended) markup:

<li class="slide">
<picture id="img-0">
    <!--[if IE 9]><video style="display: none;"><![endif]-->
    <source srcset="[email protected] 2x, image-01-1600x700.jpg 1x" media="(min-width:1281px)">
    <source srcset="[email protected] 2x, image-01-1280x560.jpg 1x" media="(min-width:1025px)">
    <source srcset="[email protected] 2x, image-01-1024x575.jpg 1x" media="(min-width:769px)">
    <source srcset="[email protected] 2x, image-01-534x355.jpg 1x">
    <!--[if IE 9]></video><![endif]-->
    <img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" srcset="[email protected] 2x, image-01-1280x560.jpg 1x" alt="My alt" />
</picture>
</li>
<li class="slide">
<picture id="img-1">
    <!--[if IE 9]><video style="display: none;"><![endif]-->
    <source data-srcset="[email protected] 2x, image-02-1600x700.jpg 1x" media="(min-width:1281px)">
    <source data-srcset="[email protected] 2x, image-02-1280x560.jpg 1x" media="(min-width:1025px)">
    <source data-srcset="[email protected] 2x, image-02-1024x575.jpg 1x" media="(min-width:769px)">
    <source data-srcset="[email protected] 2x, image-02-534x355.jpg 1x">
    <!--[if IE 9]></video><![endif]-->                              
    <!--[if gte IE 9]><!-->
        <img class="lazyload" data-srcset="[email protected] 2x, image-02-1280x560.jpg 1x" alt="My alt" />
    <!--<![endif]-->
    <!--[if lt IE 9]><img src="image-02-1280x560.jpg" width="1280" height="560" alt="My alt" /><![endif]-->
</picture>
</li>
...etc

Now I would like to pass the W3C validation, but it gives me a lot of these errors:
A source element that has a following sibling source element or img element with a srcset attribute must have a media attribute and/or type attribute.
and
Element source is missing required attribute srcset.

I tried to add empty srcset in the source elements in slide 2 and up, but that doesn't help (even more errors). Can these errors somehow be prevented or should I just live with them?

Thanks a lot!

Add option for default image if 404

Hello,

Thanks for this cool library. I just started to test it and use it on a dev server and it seems pretty effective and fast.

I just have one particular issue that made me thinking about a possible improvement.
tl;dr : Is it possible to add an option for replacing the image by a default one if it's not available (404 or other) ?

Explanation :
I work on an e-commerce website, and we have some results pages with huge products lists. These pages are displaying a lot of images, but the difficulty is that we can't be sure of the availability for each file (sometimes suppliers don't send us the files for the whole products catalog, and we have to fill the holes by ourselves as and when we notice). Testing this availability on the server side is too slow on the biggest pages because that means one HTTP request per image (they are hosted on a different server so I can't have a direct access to the file system).
That's why I removed this test from the server script and now I just send my tags with a "loader.gif" for src attribute's value. I use lazysizes to replace this loader by the original image via data-src attribute, but the issue is at this moment I'm still not sure of image availability.

I want to use a "no-photo.jpg" file for replacing missing images, and I don't want to set it as default src value because it will shows up for everyone before lazysizes does his job. As this picture is a crossed camera, that wouldn't be ideal.
So I would like a way to simply define this generic default file which will be used by lazysizes for replacing all unavailable images. I was simply thinking of a new option for this purpose, I hope that's not to nasty to implement.

Please, let me know your thoughts about this.

Video support

It would be great if it could also work with <video>:

  • support of the poster image
  • setting the src attribute of <video> or <source> lazily

It might be outside the range of this module but I thought I'd ask anyway :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.