Static data
Simple, tiny, no dependency, lazy loader. Source code available on github.com/area17/lazyload.
Doesn't preload, unload, mess with media queries, emit events, offer APIs etc.
Uses IntersectionObserver
if available and if not, it uses a throttled requestAnimationFrame
if available. If neither are available it does nothing.
When an element is in the view port it swaps data-src/data-srcset
on img
, source
and iframes
to src/srcset
. It also adds a load listener and removes the data-
attribute on load to allow you to hook styles up to the two different states.
It will also look for data-lazyload
and swap that attribute for data-lazyloaded
; again so you can hook up styles to the two different states.
If data-srcset
to srcset
and picturefill is present, attempts to run picturefill on the element.
When it runs out of elements to watch, the loop ends.
NB: v0.1.0 of @area17/a17-lazyload correlates to v2.1.1 of the original developmentSetting up
In your HTML:
<script src="path/to/lazyload.min.js"></script>
In your JavaScript (on DOM ready):
document.addEventListener('DOMContentLoaded', function(){
lazyload();
});
Also available via NPM:
npm install @area17/a17-lazyload
Remember to import it:
import lazyload from '@area17/a17-lazyload';
document.addEventListener('DOMContentLoaded', function(){
lazyload();
});
Options
These options are the defaults, and can be overridden on init:
var options = {
namespace: '', // add custom name to attributes ie: data-'namespace'-src
pageUpdatedEventName: 'page:updated', // how your app tells the rest of the app an update happened
elements: 'img[data-src], img[data-srcset], source[data-srcset], iframe[data-src], video[data-src], [data-lazyload]', // maybe you just want images?
rootMargin: '0px', // IntersectionObserver option
threshold: 0, // IntersectionObserver option
maxFrameCount: 10, // 60fps / 10 = 6 times a second
forceAutoplayVideoPlay: true // force autoplay of autoplay videos
};
lazyload(options);
namespace
- string - a string for custom attributes naming, ie: data-'namespace'-src. Defaults to none. This is applied to all data attributes: src, srcset, lazyload, lazyloaded
pageUpdatedEventName
- string - an event name to listen for when the page has new content that might need to be lazy loaded. If set to `false` lazyLoad will only run on initial page load.
elements
- string - string of items to look to lazy load.
rootMargin
- string - IntersectionObserver rootMargin option.
threshold
- integer/array - IntersectionObserver threshold option.
maxFrameCount
- integer - as
requestAnimationFrame
runs as the monitor refreshes, this could be 60 times a second, to throttle this we can tell the script every NUM of frames. forceAutoplayVideoPlay
> 0.1.2- boolean - defaults to
true
, iOS Safari doesn't always autoplay lazy loaded videos with the autoplay attribute, this will attempt to force it, but beware, it potentially replaces the video in order to force Safari to play it, which will likely mean any event listeners you have on the video will be lost. You may need to alter your JavaScript or disable this option.
Useful CSS
This demo page uses the following CSS:
picture,
img,
iframe {
display: block;
border: 0 none;
opacity: 1;
transition: opacity .25s;
width: 500px;
height: 281px;
background: #f2f2f2;
outline: 0 none;
}
iframe {
width: 560px;
height: 315px;
}
img[data-src]:not([src^="data:image"]),
img[data-srcset]:not([src^="data:image"]),
iframe[data-src] {
opacity: 0;
}
img[data-srcset][src=""] {
content: url("data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==");
}
Its well advisable to give the images/picture/iframes an intrinsic size to stop huge repaints: Either by giving a pixel size and using a transparent gif:
<img width="500" height="281" data-src="./images/greenflash_800.jpg" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">
Or, using the padding trick:
.img-container {
position: relative;
height: 0;
padding-bottom: 56.25%; // for 16:9 images
}
.img-container img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
Standard image, no src

<img data-src="./images/greenflash_800.jpg">
Standard image, src=""

<img src="" data-src="./images/greenflash_800.jpg">
Image on different domain

<img data-src="https://area17.imgix.net/26b6abd1-b18e-4cd0-87c2-1687d6c30a6a/nytimes-events_photo_04.jpg?auto=compress%2Cformat&fit=min&fm=jpg&ixjsv=2.2.4&q=90&rect=0%2C0%2C2880%2C1620&w=480" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">
Standard image with LQIP

<img data-src="./images/greenflash_800.jpg" src="data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAABAAD/4QN8aHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjUtYzAxNCA3OS4xNTE0ODEsIDIwMTMvMDMvMTMtMTI6MDk6MTUgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6Y2QwNDkwYzktYTE1Yy00OTY2LTg2MWMtM2QwMWNjODk2MjhkIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkFDMjExNDdBQjRERDExRTY5M0NCRTVBNkJEODRGOTJCIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkFDMjExNDc5QjRERDExRTY5M0NCRTVBNkJEODRGOTJCIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjcyMzI0NTQ5LWFlMGEtNDlmZi1iNjBkLTdhYjZjNzUzOTUxMCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpjZDA0OTBjOS1hMTVjLTQ5NjYtODYxYy0zZDAxY2M4OTYyOGQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAaGRknHCc+JSU+Qi8vL0JHPTs7PUdHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHARwnJzMmMz0mJj1HPTI9R0dHRERHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0f/wAARCAA4AGQDASIAAhEBAxEB/8QBGwAAAwEBAQEBAQEBAQAAAAAAAQACAwQFBgcICQoLAQEBAQEBAQEBAQEBAQAAAAAAAQIDBAUGBwgJCgsQAAICAQMCAwQHBgMDBgIBNQEAAhEDIRIxBEFRIhNhcTKBkbFCoQXRwRTwUiNyM2LhgvFDNJKishXSUyRzwmMGg5Pi8qNEVGQlNUUWJnQ2VWWzhMPTdePzRpSkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2EQACAgAFAQYGAQMBAwUDBi8AARECIQMxQRJRYXGBkSITMvChsQTB0eHxQlIjYnIUkjOCQySisjRTRGNzwtKDk6NU4vIFFSUGFiY1ZEVVNnRls4TD03Xj80aUpIW0lcTU5PSltcXV5fVWZnaG/9oADAMBAAIRAxEAPwDipNOm1O10QgBoBsRaEWAik7XURaEWFMNq7Xo2J2KSwcpizT1GDmYqSGFIp2MWCGgzpW6VA6BBoQdQHQRcSagwGNrY9Ii1tZIg5drQi77EiCkQZCK7Xfau1klOYxczB7DFgxbIOMwczF7TBzMGySDk2q9GxVJINQ6B5hN0E3nJuDpDYeYTdBNzJqDamqcRNreySwaIY3oM1JILZLG9kzbIgosFBm5mbSQVSue9UDhGRsZFV0CxkbGRVclKGRr1FVhofUQciqsAScjJyKrcDJByMnIqtIT6iqrQf//Z">
Simple responsive image

<img src="" data-srcset="./images/greenflash_800.jpg 800w, ./images/greenflash_400.jpg 400w" sizes="500px">
Responsive image with LQIP

<img data-srcset="./images/greenflash_800.jpg 800w, ./images/greenflash_400.jpg 400w" sizes="500px" src="data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAABAAD/4QN8aHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjUtYzAxNCA3OS4xNTE0ODEsIDIwMTMvMDMvMTMtMTI6MDk6MTUgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6Y2QwNDkwYzktYTE1Yy00OTY2LTg2MWMtM2QwMWNjODk2MjhkIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkFDMjExNDdBQjRERDExRTY5M0NCRTVBNkJEODRGOTJCIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkFDMjExNDc5QjRERDExRTY5M0NCRTVBNkJEODRGOTJCIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjcyMzI0NTQ5LWFlMGEtNDlmZi1iNjBkLTdhYjZjNzUzOTUxMCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpjZDA0OTBjOS1hMTVjLTQ5NjYtODYxYy0zZDAxY2M4OTYyOGQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAaGRknHCc+JSU+Qi8vL0JHPTs7PUdHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHARwnJzMmMz0mJj1HPTI9R0dHRERHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0f/wAARCAA4AGQDASIAAhEBAxEB/8QBGwAAAwEBAQEBAQEBAQAAAAAAAQACAwQFBgcICQoLAQEBAQEBAQEBAQEBAQAAAAAAAQIDBAUGBwgJCgsQAAICAQMCAwQHBgMDBgIBNQEAAhEDIRIxBEFRIhNhcTKBkbFCoQXRwRTwUiNyM2LhgvFDNJKishXSUyRzwmMGg5Pi8qNEVGQlNUUWJnQ2VWWzhMPTdePzRpSkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2EQACAgAFAQYGAQMBAwUDBi8AARECIQMxQRJRYXGBkSITMvChsQTB0eHxQlIjYnIUkjOCQySisjRTRGNzwtKDk6NU4vIFFSUGFiY1ZEVVNnRls4TD03Xj80aUpIW0lcTU5PSltcXV5fVWZnaG/9oADAMBAAIRAxEAPwDipNOm1O10QgBoBsRaEWAik7XURaEWFMNq7Xo2J2KSwcpizT1GDmYqSGFIp2MWCGgzpW6VA6BBoQdQHQRcSagwGNrY9Ii1tZIg5drQi77EiCkQZCK7Xfau1klOYxczB7DFgxbIOMwczF7TBzMGySDk2q9GxVJINQ6B5hN0E3nJuDpDYeYTdBNzJqDamqcRNreySwaIY3oM1JILZLG9kzbIgosFBm5mbSQVSue9UDhGRsZFV0CxkbGRVclKGRr1FVhofUQciqsAScjJyKrcDJByMnIqtIT6iqrQf//Z">
Simple <picture>, no src
<picture>
<source data-srcset="./images/greenflash_400.jpg, ./images/greenflash_800.jpg 2x" media="(min-width: 800px)">
<source data-srcset="./images/greenflash_400.jpg, ./images/greenflash_800.jpg 2x" media="(max-width: 799px)">
<img>
</picture>
Simple <picture>, src="./images/greenflash_100.jpg"
(LQIP)

<picture>
<source data-srcset="./images/greenflash_400.jpg, ./images/greenflash_800.jpg 2x" media="(min-width: 800px)">
<source data-srcset="./images/greenflash_400.jpg, ./images/greenflash_800.jpg 2x" media="(max-width: 799px)">
<img src="./images/greenflash_100.jpg">
</picture>
<picture> with inline LQIP
<picture>
<source data-srcset="./images/greenflash_400.jpg, ./images/greenflash_800.jpg 2x" media="(min-width: 800px)">
<source data-srcset="./images/greenflash_400.jpg, ./images/greenflash_800.jpg 2x" media="(max-width: 799px)">
<img src="data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAABAAD/4QN8aHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjUtYzAxNCA3OS4xNTE0ODEsIDIwMTMvMDMvMTMtMTI6MDk6MTUgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6Y2QwNDkwYzktYTE1Yy00OTY2LTg2MWMtM2QwMWNjODk2MjhkIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkFDMjExNDdBQjRERDExRTY5M0NCRTVBNkJEODRGOTJCIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkFDMjExNDc5QjRERDExRTY5M0NCRTVBNkJEODRGOTJCIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjcyMzI0NTQ5LWFlMGEtNDlmZi1iNjBkLTdhYjZjNzUzOTUxMCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpjZDA0OTBjOS1hMTVjLTQ5NjYtODYxYy0zZDAxY2M4OTYyOGQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAaGRknHCc+JSU+Qi8vL0JHPTs7PUdHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHARwnJzMmMz0mJj1HPTI9R0dHRERHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0f/wAARCAA4AGQDASIAAhEBAxEB/8QBGwAAAwEBAQEBAQEBAQAAAAAAAQACAwQFBgcICQoLAQEBAQEBAQEBAQEBAQAAAAAAAQIDBAUGBwgJCgsQAAICAQMCAwQHBgMDBgIBNQEAAhEDIRIxBEFRIhNhcTKBkbFCoQXRwRTwUiNyM2LhgvFDNJKishXSUyRzwmMGg5Pi8qNEVGQlNUUWJnQ2VWWzhMPTdePzRpSkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2EQACAgAFAQYGAQMBAwUDBi8AARECIQMxQRJRYXGBkSITMvChsQTB0eHxQlIjYnIUkjOCQySisjRTRGNzwtKDk6NU4vIFFSUGFiY1ZEVVNnRls4TD03Xj80aUpIW0lcTU5PSltcXV5fVWZnaG/9oADAMBAAIRAxEAPwDipNOm1O10QgBoBsRaEWAik7XURaEWFMNq7Xo2J2KSwcpizT1GDmYqSGFIp2MWCGgzpW6VA6BBoQdQHQRcSagwGNrY9Ii1tZIg5drQi77EiCkQZCK7Xfau1klOYxczB7DFgxbIOMwczF7TBzMGySDk2q9GxVJINQ6B5hN0E3nJuDpDYeYTdBNzJqDamqcRNreySwaIY3oM1JILZLG9kzbIgosFBm5mbSQVSue9UDhGRsZFV0CxkbGRVclKGRr1FVhofUQciqsAScjJyKrcDJByMnIqtIT6iqrQf//Z">
</picture>
iFrame
<iframe data-src="https://www.youtube.com/embed/Wji-BZ0oCwg?list=PL148kCvXk8pDWYE9q9cNdux5JFmu80kN8" width="560" height="315" frameborder="0" allowfullscreen></iframe>