Skip to content

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

Notifications You must be signed in to change notification settings

aFarkas/lazysizes

Repository files navigation

lazysizes

lazysizesis a fast (jank-free), SEO-friendly and self-initializing lazyloader for images (including responsive imagespicture/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 thesizesattribute for your responsive images, it allows you to share media queries for yourmediaattributes 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 thelazysizes.min.js scriptand includelazysizesin your webpage. (Or install via npm:npm install lazysizes --saveor bowerbower install lazysizes --save)

    <scriptsrc= "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 seehere.

  2. lazysizes does not need any JS configuration: Add theclass"lazyload"to your images/iframes in conjunction with adata-srcand/ordata-srcsetattribute. Optionally you can also add asrcattribute with a low quality image:

    <!-- non-responsive: -->
    <imgdata-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 -->
    <iframeframeborder= "0"
    class= "lazyload"
    allowfullscreen= ""
    data-src= "// youtube /embed/ZfV-aYdU4uE">
    </iframe>

Can be seenhere

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 likepicturefillor use the extreme lightweight partialrespimg polyfill pluginor theresponsive image on demand plugin.Alternatively, you can simply define a fallback src via thedata-srcattribute. If you want to learn more about the responsive image syntax read "The anatomy of responsive images".

What makes lazysizes so awesome:

lazysizesis 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:hoveror 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 theattrchange/re-initialization extension)).
  2. Future-proof:It directly includes standard responsive image support (pictureandsrcset)
  3. Separation of concerns:For responsive image support it adds an automaticsizescalculation 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 (runtimeandnetwork) 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 theavailable 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 alsoexpand,expFactorandloadModeoptions). 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

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

Markup API

Add theclasslazyloadto allimgandiframeelements, which should be loaded lazy.Insteadof asrcorsrcsetattribute use adata-srcordata-srcsetattribute:

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

Automatically setting thesizesattribute

lazysizessupports setting thesizesattribute automatically, corresponding to the current size of your image - just set the value ofdata-sizestoauto.

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

Important: Howsizesis 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 usewidth: auto). Often the following general CSS rule might help:img[data-sizes= "auto" ] { display: block; width: 100%; }(see alsospecifying image/iframe dimensions with the recommended aspect ratio definition). If it is below40(can be configured through theminSizeoption), lazysizes traverses up the DOM tree until it finds a parent which is over40and uses this number.

The width auto-calculated by lazysizes can be modified using thelazybeforesizesevent (lazybeforesizes documentation). Alternatively, theparent fit plugincan 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 ofobject-fit).

Thedata-sizes= "auto"feature only makes sense if you use thedata-srcsetattribute withwidthdescriptors which allows the most appropriate image can be selected (It does not make sense if you use the x descriptor or onlysrc.).

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 thepictureelement.)

Simple pattern

Add the classlazyloadand simply omit thesrcattribute or add a data uri as fallbacksrc.

<!-- responsive adaptive example -->

<img
class= "lazyload"
data-srcset= "image.jpg 1x, image2.jpg 2x"
alt= "my image"/>
<!-- retina optimized example -->
<imgclass= "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 eithersrcset/data-srcsetorpicture,we recommend to extend this pattern with either adata-src(see next pattern: "Combinedata-srcsetwithdata-src") or with a suitablesrcattribute (see: "modern pattern" or "LQIP" ).

Combinedata-srcsetwithdata-src

In case you want to use responsive images for supporting browsers, but don't want to include a polyfill, simply combine yourdata-srcsetwith adata-srcattribute.

<!-- 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 thedata-srcwill 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 fallbacksrc.

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 thesrc:

<!-- 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: -->
<imgsrc= "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 ourlazysizes 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>

<imgsrc= "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>

<divclass= "ratio-box fade-box">
<imgsrc= "lqip-src.jpg"/>
<imgdata-src= "image.jpg"class= "lazyload"/>
</div>

modern transparentsrcsetpattern

Combine a normalsrcattribute with a transparent or low quality image assrcsetvalue and adata-srcsetattribute. This way modern browsers will lazy load without loading thesrcattribute and all others will simply fallback to the initialsrcattribute (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 anoscriptelement.

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

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

Note: As an alternative to the noscript pattern also checkout thenoscript 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 theexpandoption.

Additionally, this general option can be overridden with thedata-expandattribute for each element. Different than the generalexpandoption thedata-expandattribute also accepts negative values (All numbers but0are 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>

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

CSS API

lazysizes adds the classlazyloadingwhile the images are loading and the classlazyloadedas 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:opacity300ms;
}
/* fade image in while loading and show a spinner as background image (good for progressive images) */

.lazyload{
opacity:0;
}

.lazyloading{
opacity:1;
transition:opacity300ms;
background:#f7f7f7url(loader.gif) no-repeat center;
}

Broken image symbol

In case you are using analtattribute but do not declare asrc/srcsetattribute you will end up with a broken image symbol.

There are two easy ways to deal with it.

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

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

JS API

lazysizesautomatically detects new elements with the classlazyloadso 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 namedlazySizesConfig.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 thelazysizesmodule:

importlazySizesfrom'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 oneclass.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 thepreloadAfterLoadoption is set tofalse.Note: Thisclasscan be also dynamically set ($currentSlide.next().find('.lazyload').addClass('lazypreload');).
  • lazySizesConfig.loadingClass(default:"lazyloading"): Thisclasswill be added toimgelement as soon as image loading starts. Can be used to add unveil effects.
  • lazySizesConfig.loadedClass(default:"lazyloaded"): Thisclasswill 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): Theexpandoption 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 between300and1000(depending on theexpFactoroption.) 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 to0if the browser is currently downloading and expand it if the browser network is currently idling and the user not scrolling (by multiplying theexpandoption with1.5(expFactor)). This option can also be overridden with the[data-expand]attribute.
  • lazySizesConfig.minSize(default:40): Fordata-sizes= "auto"feature. The minimum size of an image that is used to calculate thesizesattribute. In case it is underminSizethe script traverses up the DOM tree until it finds a parent that is overminSize.
  • lazySizesConfig.srcAttr(default:"data-src"): The attribute, which should be transformed tosrc.
  • lazySizesConfig.srcsetAttr(default:"data-srcset"): The attribute, which should be transformed tosrcset.
  • lazySizesConfig.sizesAttr(default:"data-sizes"): The attribute, which should be transformed tosizes.Makes almost only makes sense with the value"auto".Otherwise, thesizesattribute should be used directly.
  • lazySizesConfig.customMedia(default:{}): ThecustomMediaoption object is an alias map for different media queries. It can be used to separate/centralize your multiple specific media queries implementation (layout) from thesource[media]attribute (content/structure) by creating labeled media queries. (See also thecustommedia extension).
  • lazySizesConfig.loadHidden(default:true): Whether to loadvisibility: hiddenelements. Important: lazySizes will load hidden images always delayed. If you want them to be loaded as fast as possible you can useopacity: 0.001but nevervisibility: hiddenoropacity: 0.
  • lazySizesConfig.ricTimeout(default:0): The timeout option used for therequestIdleCallback.Reasonable values between: 0, 100 - 1000. (Values below 50 disable therequestIdleCallbackfeature.)
  • 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): TheexpFactoris used to calculate the "preload expand", by multiplying the normalexpandwith theexpFactorwhich is used to preload assets while the browser is idling (no important network traffic and no scrolling). (Reasonable values are between1.5and4depending on theexpandoption).
  • lazySizesConfig.hFac(default:0.8): ThehFac(horizontal factor) modifies the horizontal expand by multiplying theexpandvalue with thehFacvalue. 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): TheloadModecan 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 (expandoption) and 3 = load also not so near view elements (expand*expFactoroption). This value is automatically set to3after onload. Change this value to1if you (also) optimize for the onload event or change it to3if 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 tofalseand calllazySizes.init();later explicitly.

JS API - events

lazysizesprovides three events to modify or extend the behavior oflazysizes.

  • 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 isdefaultPreventedthe default transformation action will be prevented (see also thels.unveilhooks.js plugin):
//add simple support for background images:
document.addEventListener('lazybeforeunveil',function(e){
varbg=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(){
varajax=$(e.target).data('ajax');
if(ajax){
$(e.target).load(ajax);
}
});

Thelazybeforeunveilcan 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>

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

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

  • lazybeforesizes:This event will be fired on each element with thedata-sizes= "auto"attribute right before the calculatedsizesattribute will be set. Theevent.detail.widthproperty is set to the calculated width of the element and can be changed to any number. In case the event isdefaultPreventedthesizesattribute won't be set. See also theparent-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 thelazySizes.loader.unveil(DOMNode)can be called:

lazySizes.loader.unveil(imgElem);

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

lazySizes.autoSizer.checkElems()

In case one or more image elements with the attributedata-sizes= "auto"have changed in sizelazySizes.autoSizer.updateElemscan 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, iflazySizesConfig.loadModewas set to0.

lazySizes.init()

LazySizes initializes itself automatically. In case you setlazySizesConfig.inittofalseyou need to explicitly calllazySizes.init().Note: You can speed up initial loading of in view images if you calllazySizesConfig.init()explicitly after lazysizes and all plugins are loaded.

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

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

Browser Support

lazysizessupports all browsers, that supportdocument.getElementsByClassName(== all browsers but not IE8-). In case you need to support IE8, see also thenoscript 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 themaster(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

Runnpx gruntto validate JSHint and uglify/minify all files.

Tests

Runnpx serverino -p 3333and navigate tohttp://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 scriptsbeforethe lazySizes main script.

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

Thesrcsetattribute with thewdescriptor andsizesattribute 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. ThelazySizes optimumx extensiongives you more control to trade between perceived quality vs. perceived performance.

Theparent fit pluginextends thedata-sizes= "auto"feature to also calculate the rightsizesforobject-fit: contain|coverimage elements and otherheight( and width) constrained image elements in general.

Theobject fit polyfill pluginpolyfills theobject-fitand theobject-positionproperty in non supporting browsers.

Theblur up / effect pluginallows you to creategreat over fade / blur up effectswith 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 thedata-src/data-srcsetattributes of already transformed lazyload elements, you must normally also re-add thelazyloadclass to the element.

Thisattrchange / re-initialization extensionautomatically detects changes to yourdata-*attributes and adds the class for you.

Theartdirect pluginallows you to fully control art direction via CSS.

There are also other plugins/extension in theplugins 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 widthandthe 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 theCSS intrinsic ratio scaling techniqueshould 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>

<divclass= "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>

<divclass= "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>

<divclass= "ratio-container unknown-ratio-container">
<img

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

or at least add amin-height(andmin-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, thedata-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 theparent 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);
varupdate=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 themin-heightpattern 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 placedbeforeany 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 calllazySizes.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.

lazysizesis 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.lazyloadelement was added by AJAX or revealed by a JS or CSS animation it will be picked up bylazysizes.

<!-- 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"/>

About

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.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published