Skip to content

Commit 75e2931

Browse files
author
aFarkas
committed
0.1.1
1 parent 554a56a commit 75e2931

File tree

7 files changed

+80
-55
lines changed

7 files changed

+80
-55
lines changed

README.md

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,33 @@
11
#lazysizes
22
**lazysizes** is a fast (jankfree) lazyloader for images (including responsive images), iframes and scripts/widgets without any dependency.
33

4+
##Features
5+
6+
* supports standard conform **responsive images** (``srcset`` and ``picture``)
7+
* loads ``iframes`` and ``script``
8+
* Optional **automatic ``sizes`` attribute calculation** for your repsonsive images (simply add ``data-sizes="auto"``). respimg was never so easy.
9+
* **easy to use** / no configuration required:
10+
* no configuration required for scrollable areas (overflow: auto/scroll)
11+
* no configuration or callback invocation required for any kind of JS widgets (tabs, carousels, accordions, dialogs) or any JS behaviors (i.e.: infinite scroll/AJAX)
12+
* performance and memory optimized
13+
* **absolutley jankfree** (decoding an image or parsing an iframe might create a jank, but the script itself will never ever, even if you had thounds of images to lazy load on one page)
14+
* uses the low quality image placeholder pattern, if an image already has a valid source
15+
* JS off syntax possible
16+
* lightweight only 2kb
17+
418
##Download and Embed
519

620
Simply download the [lazysizes.min.js](lazysizes.min.js) and include it in your webpage:
721

822
```html
9-
<script src="lazysizes.min.js"></script>
23+
<script src="lazysizes.min.js" async=""></script>
1024
```
1125

1226
##[Demo with code examples](http://afarkas.github.io/lazysizes/#examples)
1327
can be seen [here](http://afarkas.github.io/lazysizes/#examples).
1428

1529
##API
16-
lazysizes comes with a simple markup and JS API:
30+
**lazysizes** comes with a simple markup and JS API:
1731

1832
###Markup API
1933
Simply 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:
@@ -24,24 +38,24 @@ Simply add the ``class`` ``lazyload`` to all ``img`` and ``iframe`` elements, wh
2438
<img data-srcset="responsive-image1.jpg 1x, responsive-image2.jpg 2x" class="lazyload" />
2539
```
2640

27-
As a nice bonus lazysizes supports setting the ``sizes`` attribute automatically corresponding to the current size of your image. To add support for this add the value ``auto`` to the ``data-sizes`` attribute:
41+
**lazysizes** supports setting the ``sizes`` attribute automatically corresponding to the current size of your image. To add support for this add the value ``auto`` to the ``data-sizes`` attribute:
2842

2943
```html
3044
<img
3145
data-sizes="auto"
32-
data-srcset="responsive-image1.jpg 300w,
46+
data-srcset="responsive-image1.jpg 300w,
3347
responsive-image2.jpg 600w,
3448
responsive-image3.jpg 900w" class="lazyload" />
3549
```
3650

37-
**How sizes is calculated**: The automatic sizes calculation takes the with of the image and the width of its parent element and uses the largeest number of those two calculated numbers. It's therefore important, that all images are contained in a wrapper that isn't much bigger than the image should shown. Otherwise a wrong (too big) sizes attribute will be calculated.
51+
**Important: How ``sizes`` is calculated**: The automatic sizes calculation takes the width of the image and the width of its parent element and uses the largest number of those two calculated numbers. It's therefore important, that all images are contained in a wrapper that isn't much bigger than the image should shown. Otherwise a wrong (too big) sizes attribute will be calculated.
3852

3953
For JS off support simply use a ``span`` or ``div`` element as a wrapper for a ``noscript`` element:
4054

4155
```html
4256
<span
4357
data-sizes="auto"
44-
data-srcset="responsive-image1.jpg 300w,
58+
data-srcset="responsive-image1.jpg 300w,
4559
responsive-image2.jpg 600w,
4660
responsive-image3.jpg 900w" class="lazyload">
4761
<noscript>
@@ -50,16 +64,23 @@ For JS off support simply use a ``span`` or ``div`` element as a wrapper for a `
5064
</span>
5165
```
5266

53-
###JS API
54-
**lazysizes** automatically detects new elements with the class ``lazyload`` so you wont need to call anything.
55-
56-
####``lazySizes.updateAllLazy``
57-
In case a lazyload image was hidden and then shown via JS the method ``lazySizes.updateAllLazy`` can be called:
67+
##recommended markup: LQIP
68+
We recommend to use the LQIP pattern: Simply add a low quality image as the ``src``:
5869

59-
```js
60-
lazySizes.updateAllLazy();
70+
```html
71+
<img
72+
data-sizes="auto"
73+
src="lqip-src.jpg"
74+
data-srcset="lqip-src.jpg 150w,
75+
image2.jpg 300w,
76+
image3.jpg 600w,
77+
image4.jpg 900w" class="lazyload" />
6178
```
6279

80+
###JS API
81+
**lazysizes** automatically detects new elements with the class ``lazyload`` so you won't need to call anything in most situations.
82+
83+
6384
####``lazySizes.unveilLazy(DOMNode)``
6485

6586
In case a developer wants to show an image even if it is not inside the viewport the ``lazySizes.unveilLazy(DOMNode)`` can be called:
@@ -77,7 +98,7 @@ lazySizes.updateAllSizes();
7798
```
7899

79100
##Browser Support
80-
**lazysizes** is supported by [all browsers which support ``getElementsByClassName``](http://caniuse.com/#feat=getelementsbyclassname). (No IE8 support.)
101+
**lazysizes** is supports the following browsers: IE9+, Firefox 21+, Chrome 27+, Safari 6.1+, iOS Safari 7.0+, Android 4.1+
81102

82103
##About responsive image support
83-
For full cross browser responsive image support a polyfill like [respimage](https://github.com/aFarkas/respimage) or [picturefill](https://github.com/scottjehl/picturefill) has to be used.
104+
For full cross browser responsive image support a polyfill like [respimage](https://github.com/aFarkas/respimage) or [picturefill](https://github.com/scottjehl/picturefill) has to be used.

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "lazysizes",
33
"repo": "afarkas/lazysizes",
4-
"version": "0.1.0",
4+
"version": "0.1.1",
55
"main": "lazysizes.min.js",
66
"scripts": [
77
"lazysizes.min.js"

component.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lazysizes",
3-
"version": "0.1.0",
3+
"version": "0.1.1",
44
"repo": "afarkas/lazysizes",
55
"main": "lazysizes.min.js",
66
"scripts": ["lazysizes.min.js"],

index.html

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ <h3>responsive image with the <code>picture</code> element</h3>
227227
<div class="row" id="autosizes-example">
228228
<div class="alert alert-info">
229229
<p><strong>automatic sizes feature</strong>: In case of lazy loading images the <code>sizes</code> attribute of the <code>img</code>/<code>source</code> elements can be calculated with JS.</p>
230-
<p>This automatic sizes feature is directly included in <strong>lazySizes<</strong>. Simply use the keyword <code>auto</code> inside of the <code>data-sizes</code> attributes (<code>data-sizes="auto"</code>).</p>
230+
<p>This automatic sizes feature is directly included in <strong>lazySizes</strong>. Simply use the keyword <code>auto</code> inside of the <code>data-sizes</code> attributes (<code>data-sizes="auto"</code>).</p>
231231
</div>
232232

233233
<div class="col-sm-12">
@@ -619,10 +619,5 @@ <h3>Widgets/Javascript/Script</h3>
619619

620620

621621
</div>
622-
<script>
623-
$(document).on('slide.bs.carousel', function(){
624-
lazySizes.updateAllLazy();
625-
});
626-
</script>
627622
</body>
628623
</html>

lazysizes.js

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
var regScript = /^script$/i;
1919
var regImg = /^img$/i;
2020
var noDataTouch = {sizes: 1, src: 1, srcset: 1};
21-
var inViewTreshhold = 99;
21+
var inViewTreshhold = 66;
2222
var lazyloadElems = document.getElementsByClassName('lazyload');
2323
var autosizesElems = document.getElementsByClassName('lazyautosizes');
2424
var setImmediate = window.setImmediate || window.setTimeout;
@@ -57,21 +57,6 @@
5757
};
5858
}
5959

60-
61-
62-
function inView(el) {
63-
var rect = el.getBoundingClientRect();
64-
var bottom, right, left, top;
65-
66-
return !!(
67-
(bottom = rect.bottom) >= (inViewTreshhold * -1) &&
68-
(top = rect.top) <= window.innerHeight + inViewTreshhold &&
69-
(right = rect.right) >= (inViewTreshhold * -1) &&
70-
(left = rect.left) <= window.innerWidth + inViewTreshhold &&
71-
(bottom || right || left || top)
72-
);
73-
}
74-
7560
function updatePolyfill(el, full){
7661
var imageData;
7762
if(window.picturefill){
@@ -108,30 +93,40 @@
10893
if(!running){
10994
running = true;
11095
clearTimeout(timer);
111-
timer = setTimeout(run, 66);
96+
timer = setTimeout(run, 99);
11297
}
11398
}
11499
};
115100
})();
116101

117102
var evalLazyElements = function (){
118-
var now, i, checkTime;
103+
var now, i, checkTime, vW, vH, rect, top, left, right, bottom, negativeTreshhold;
119104
var len = lazyloadElems.length;
120105
if(len){
121106
now = Date.now();
122107
checkTime = 0;
108+
vW = window.innerWidth + inViewTreshhold;
109+
vH = window.innerHeight + inViewTreshhold;
110+
negativeTreshhold = inViewTreshhold * -1;
123111

124112
i = globalLazyIndex || 0;
125113

126114
clearLazyTimer();
127115

128116
for(; i < len; i++){
129-
if (inView(lazyloadElems[i])){
117+
rect = lazyloadElems[i].getBoundingClientRect();
118+
119+
if ((bottom = rect.bottom) >= negativeTreshhold &&
120+
(top = rect.top) <= vH &&
121+
(right = rect.right) >= negativeTreshhold &&
122+
(left = rect.left) <= vW &&
123+
(bottom || right || left || top)){
130124
unveilLazy(lazyloadElems[i]);
131125
} else {
132126
checkTime++;
133127
if(2 < checkTime && i < len - 1 && Date.now() - now > 9){
134128
globalLazyIndex = i + 1;
129+
135130
globalLazyTimer = setTimeout(evalLazyElements, 20);
136131
break;
137132
}
@@ -285,6 +280,7 @@
285280

286281
if(i > checkTime && i < len - 1 && Date.now() - now > 9){
287282
globalSizesIndex = i + 1;
283+
288284
globalSizesTimer = setTimeout(evalSizesElements, 20);
289285
break;
290286
}
@@ -308,7 +304,8 @@
308304
elemWidth :
309305
parentWidth;
310306

311-
if(width){
307+
if(width && (!elem._lazysizesWidth || width > elem._lazysizesWidth)){
308+
elem._lazysizesWidth = width;
312309
width += 'px';
313310
elem.setAttribute('sizes', width);
314311

@@ -326,33 +323,45 @@
326323
}
327324
}
328325

326+
// bind to all possible events ;-) This might look like a performance disaster, but it isn't.
327+
// The main check functions are written to run extreme fast without consuming memory.
329328
var onload = function(){
330329
inViewTreshhold *= 3;
331330
clearTimeout(globalInitialTimer);
331+
332+
document.addEventListener('load', lazyEvalLazy.throttled, true);
333+
};
334+
var onready = function(){
332335
if(window.MutationObserver){
333-
new MutationObserver( lazyEvalLazy.debounce ).observe( document.body || document.documentElement, {childList: true, subtree: true} );
336+
new MutationObserver( lazyEvalLazy.throttled ).observe( document.body || document.documentElement, {childList: true, subtree: true, attributes: true} );
334337
} else {
335-
(document.body || document.documentElement).addEventListener( "DOMNodeInserted", lazyEvalLazy.debounce, true);
338+
(document.body || document.documentElement).addEventListener( "DOMNodeInserted", lazyEvalLazy.throttled, true);
339+
(document.body || document.documentElement).addEventListener( "DOMAttrModified", lazyEvalLazy.throttled, true);
336340
}
337-
document.body.addEventListener('scroll', lazyEvalLazy.throttled, true);
338341
};
339342

340-
window.addEventListener('scroll', lazyEvalLazy.throttled, false);
341343

342-
window.addEventListener('resize', lazyEvalLazy.debounce, false);
343-
document.addEventListener('load', lazyEvalLazy.debounce, true);
344+
window.addEventListener('scroll', lazyEvalLazy.throttled, false);
345+
(document.body || document.documentElement).addEventListener('scroll', lazyEvalLazy.throttled, true);
344346

345-
document.addEventListener('touchmove', lazyEvalLazy.debounce, true);
346-
document.addEventListener('readystatechange', lazyEvalLazy.debounce, false);
347+
document.addEventListener('touchmove', lazyEvalLazy.throttled, false);
347348

349+
window.addEventListener('resize', lazyEvalLazy.debounce, false);
348350
window.addEventListener('resize', lazyEvalSizes, false);
349351

352+
if( /^i|^loade|c/.test(document.readyState) ){
353+
onready();
354+
} else {
355+
document.addEventListener('DOMContentLoaded', onready, false);
356+
}
357+
350358
if(document.readyState == 'complete'){
351359
onload();
352360
} else {
353361
window.addEventListener('load', onload, false);
362+
document.addEventListener('readystatechange', lazyEvalLazy.throttled, false);
354363
}
355-
lazyEvalLazy.debounce();
364+
lazyEvalLazy.throttled();
356365

357366
return {
358367
updateAllSizes: lazyEvalSizes,

0 commit comments

Comments
 (0)