Comparing version 2.2.2 to 2.3.0
223
dist/yall.js
'use strict'; | ||
/** | ||
* yall.js version 2.2.2 | ||
* Yet Another Lazy loader | ||
**/ | ||
function yall (options) { | ||
if (!options) { | ||
options = {}; | ||
} | ||
// The eponymous function | ||
function yall (userOptions) { | ||
// Environmental stuff. Stores feature support information, as well as other | ||
// stuff yall needs to refer to during operation. | ||
const env = { | ||
intersectionObserverSupport: "IntersectionObserver" in window && "IntersectionObserverEntry" in window && "intersectionRatio" in window.IntersectionObserverEntry.prototype, | ||
mutationObserverSupport: "MutationObserver" in window, | ||
idleCallbackSupport: "requestIdleCallback" in window, | ||
eventsToBind: [ | ||
[document, "scroll"], | ||
[document, "touchmove"], | ||
[window, "resize"], | ||
[window, "orientationchange"] | ||
] | ||
}; | ||
// Default options, merged with user options. | ||
const options = { | ||
lazyClass: "lazy", | ||
lazyBackgroundClass: "lazy-bg", | ||
lazyBackgroundLoaded: "lazy-bg-loaded", | ||
throttleTime: 200, | ||
idlyLoad: false, | ||
idleLoadTimeout: 100, | ||
threshold: 200, | ||
observeChanges: false, | ||
observeRootSelector: "body", | ||
mutationObserverOptions: { | ||
childList: true, | ||
subtree: true | ||
}, | ||
...userOptions | ||
}; | ||
// CSS selector for all the lazy little elements. | ||
const selectorString = `img.${options.lazyClass},video.${options.lazyClass},iframe.${options.lazyClass},.${options.lazyBackgroundClass}`; | ||
// Options that get passed to requestIdleCallback | ||
const intersectionObserverSupport = "IntersectionObserver" in window && "IntersectionObserverEntry" in window && "intersectionRatio" in window.IntersectionObserverEntry.prototype; | ||
const idleCallbackSupport = "requestIdleCallback" in window; | ||
const eventsToBind = [ | ||
[document, "scroll"], | ||
[document, "touchmove"], | ||
[window, "resize"], | ||
[window, "orientationchange"] | ||
]; | ||
const lazyClass = options.lazyClass || "lazy"; | ||
const lazyBackgroundClass = options.lazyBackgroundClass || "lazy-bg"; | ||
const idleLoadTimeout = options.idleLoadTimeout || 100; | ||
const threshold = options.threshold || 200; | ||
const observeChanges = options.observeChanges || false; | ||
const selectorString = `img.${lazyClass},video.${lazyClass},iframe.${lazyClass},.${lazyBackgroundClass}`; | ||
const dataAttrs = ["srcset", "src", "poster"]; | ||
const idleCallbackOptions = { | ||
timeout: options.idleLoadTimeout | ||
timeout: idleLoadTimeout | ||
}; | ||
// This small abstraction saves a few bytes. | ||
const sliceCall = arr => [].slice.call(arr); | ||
@@ -56,37 +31,43 @@ | ||
const yallLoad = element => { | ||
// Lazy load <img> elements | ||
if (element.tagName === "IMG") { | ||
let parentElement = element.parentNode; | ||
switch (element.nodeName) { | ||
case "IMG": | ||
let parentElement = element.parentNode; | ||
// Is the parent element a <picture>? | ||
if (parentElement.tagName === "PICTURE") { | ||
sliceCall(parentElement.querySelectorAll("source")).forEach(source => yallFlipDataAttrs(source)); | ||
} | ||
// Is the parent element a <picture>? | ||
if (parentElement.nodeName == "PICTURE") { | ||
sliceCall(parentElement.querySelectorAll("source")).forEach(source => { | ||
yallFlipDataAttrs(source); | ||
}); | ||
} | ||
yallFlipDataAttrs(element); | ||
} | ||
yallFlipDataAttrs(element); | ||
// Lazy load <video> elements | ||
if (element.tagName === "VIDEO") { | ||
sliceCall(element.querySelectorAll("source")).forEach(source => yallFlipDataAttrs(source)); | ||
break; | ||
// We didn't need this before, but with the addition of lazy loading | ||
// `poster` images, we need to run the flip attributes function on the | ||
// video element itself so we can trigger lazy loading behavior on those. | ||
yallFlipDataAttrs(element); | ||
case "VIDEO": | ||
sliceCall(element.querySelectorAll("source")).forEach(source => { | ||
yallFlipDataAttrs(source); | ||
}); | ||
if (element.autoplay === true) { | ||
element.load(); | ||
} | ||
} | ||
// We didn't need this before, but with the addition of lazy loading | ||
// `poster` images, we need to run the flip attributes function on the | ||
// video element itself so we can trigger lazy loading behavior on those. | ||
yallFlipDataAttrs(element); | ||
// Lazy load <iframe> elements | ||
if (element.tagName === "IFRAME") { | ||
yallFlipDataAttrs(element); | ||
if (element.autoplay) { | ||
element.load(); | ||
} | ||
break; | ||
case "IFRAME": | ||
yallFlipDataAttrs(element); | ||
break; | ||
} | ||
// Lazy load CSS background images | ||
if (element.classList.contains(options.lazyBackgroundClass)) { | ||
element.classList.remove(options.lazyBackgroundClass); | ||
element.classList.add(options.lazyBackgroundLoaded); | ||
if (element.classList.contains(lazyBackgroundClass)) { | ||
element.classList.remove(lazyBackgroundClass); | ||
element.classList.add(options.lazyBackgroundLoaded || "lazy-bg-loaded"); | ||
} | ||
@@ -98,15 +79,7 @@ }; | ||
const yallFlipDataAttrs = element => { | ||
// Do `srcset` first. Doing `src` first can cause loading of additional | ||
// assets on Safari (and possibly other webkit browsers). | ||
if (element.getAttribute("data-srcset") !== null) { | ||
element.setAttribute("srcset", element.getAttribute("data-srcset")); | ||
} | ||
if (element.getAttribute("data-src") !== null) { | ||
element.setAttribute("src", element.getAttribute("data-src")); | ||
} | ||
if (element.getAttribute("data-poster") !== null) { | ||
element.setAttribute("poster", element.getAttribute("data-poster")); | ||
} | ||
dataAttrs.forEach(dataAttr => { | ||
if (dataAttr in element.dataset) { | ||
element[dataAttr] = element.dataset[dataAttr]; | ||
} | ||
}); | ||
}; | ||
@@ -116,6 +89,6 @@ | ||
// (and other) event handlers to load images the "old" way. | ||
const yallBack = function() { | ||
const yallBack = () => { | ||
let active = false; | ||
if (active === false && lazyElements.length > 0) { | ||
if (!active && lazyElements.length) { | ||
active = true; | ||
@@ -125,4 +98,4 @@ | ||
lazyElements.forEach(lazyElement => { | ||
if (lazyElement.getBoundingClientRect().top <= (window.innerHeight + options.threshold) && lazyElement.getBoundingClientRect().bottom >= -(options.threshold) && getComputedStyle(lazyElement).display !== "none") { | ||
if (options.idlyLoad === true && env.idleCallbackSupport === true) { | ||
if (lazyElement.getBoundingClientRect().top <= (window.innerHeight + threshold) && lazyElement.getBoundingClientRect().bottom >= -threshold && getComputedStyle(lazyElement).display != "none") { | ||
if (idleCallbackSupport && idleLoadTimeout) { | ||
requestIdleCallback(() => { | ||
@@ -135,4 +108,4 @@ yallLoad(lazyElement); | ||
lazyElement.classList.remove(options.lazyClass); | ||
lazyElements = lazyElements.filter(element => element !== lazyElement); | ||
lazyElement.classList.remove(lazyClass); | ||
lazyElements = lazyElements.filter(element => element != lazyElement); | ||
} | ||
@@ -143,6 +116,8 @@ }); | ||
if (lazyElements.length === 0 && options.observeChanges === false) { | ||
env.eventsToBind.forEach(eventPair => eventPair[0].removeEventListener(eventPair[1], yallBack)); | ||
if (!lazyElements.length && !observeChanges) { | ||
eventsToBind.forEach(eventPair => { | ||
eventPair[0].removeEventListener(eventPair[1], yallBack); | ||
}); | ||
} | ||
}, options.throttleTime); | ||
}, options.throttleTime || 200); | ||
} | ||
@@ -153,10 +128,22 @@ }; | ||
if (env.intersectionObserverSupport === true) { | ||
// If the current user agent is a known crawler, immediately load all media | ||
// for the elements yall is listening for and halt execution (good for SEO). | ||
if (/(google|bing|yandex|duckduck)bot/i.test(navigator.userAgent)) { | ||
lazyElements.forEach(lazyElement => { | ||
yallLoad(lazyElement); | ||
}); | ||
return; | ||
} | ||
if (intersectionObserverSupport) { | ||
var intersectionListener = new IntersectionObserver((entries, observer) => { | ||
entries.forEach(entry => { | ||
if (entry.isIntersecting === true || entry.intersectionRatio > 0) { | ||
if (entry.isIntersecting) { | ||
let element = entry.target; | ||
if (options.idlyLoad === true && env.idleCallbackSupport === true) { | ||
requestIdleCallback(() => yallLoad(element), idleCallbackOptions); | ||
if (idleCallbackSupport && idleLoadTimeout) { | ||
requestIdleCallback(() => { | ||
yallLoad(element); | ||
}, idleCallbackOptions); | ||
} else { | ||
@@ -166,31 +153,41 @@ yallLoad(element); | ||
element.classList.remove(options.lazyClass); | ||
element.classList.remove(lazyClass); | ||
observer.unobserve(element); | ||
lazyElements = lazyElements.filter(lazyElement => lazyElement !== element); | ||
lazyElements = lazyElements.filter(lazyElement => lazyElement != element); | ||
} | ||
}); | ||
}, { | ||
rootMargin: `${options.threshold}px 0%` | ||
rootMargin: `${threshold}px 0%` | ||
}); | ||
lazyElements.forEach(lazyElement => intersectionListener.observe(lazyElement)); | ||
lazyElements.forEach(lazyElement => { | ||
intersectionListener.observe(lazyElement); | ||
}); | ||
} else { | ||
env.eventsToBind.forEach(eventPair => eventPair[0].addEventListener(eventPair[1], yallBack)); | ||
eventsToBind.forEach(eventPair => { | ||
eventPair[0].addEventListener(eventPair[1], yallBack); | ||
}); | ||
yallBack(); | ||
} | ||
if (env.mutationObserverSupport === true && options.observeChanges === true) { | ||
new MutationObserver(mutations => mutations.forEach(() => { | ||
sliceCall(document.querySelectorAll(selectorString)).forEach(newElement => { | ||
if (lazyElements.indexOf(newElement) === -1) { | ||
lazyElements.push(newElement); | ||
if ("MutationObserver" in window && observeChanges) { | ||
new MutationObserver(mutations => { | ||
mutations.forEach(() => { | ||
sliceCall(document.querySelectorAll(selectorString)).forEach(newElement => { | ||
if (lazyElements.indexOf(newElement) == -1) { | ||
lazyElements.push(newElement); | ||
if (env.intersectionObserverSupport === true) { | ||
intersectionListener.observe(newElement); | ||
} else { | ||
yallBack(); | ||
if (intersectionObserverSupport) { | ||
intersectionListener.observe(newElement); | ||
} else { | ||
yallBack(); | ||
} | ||
} | ||
} | ||
}); | ||
}); | ||
})).observe(document.querySelector(options.observeRootSelector), options.mutationObserverOptions); | ||
}).observe(document.querySelector(options.observeRootSelector || "body"), options.mutationObserverOptions || { | ||
childList: true, | ||
subtree: true | ||
}); | ||
} | ||
@@ -197,0 +194,0 @@ } |
@@ -1,2 +0,2 @@ | ||
/* yall.js v2.2.2 */ | ||
var yall=function(){"use strict";function _extends(){return(_extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}return function(e){var t={intersectionObserverSupport:"IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype,mutationObserverSupport:"MutationObserver"in window,idleCallbackSupport:"requestIdleCallback"in window,eventsToBind:[[document,"scroll"],[document,"touchmove"],[window,"resize"],[window,"orientationchange"]]},r=_extends({lazyClass:"lazy",lazyBackgroundClass:"lazy-bg",lazyBackgroundLoaded:"lazy-bg-loaded",throttleTime:200,idlyLoad:!1,idleLoadTimeout:100,threshold:200,observeChanges:!1,observeRootSelector:"body",mutationObserverOptions:{childList:!0,subtree:!0}},e),n="img."+r.lazyClass+",video."+r.lazyClass+",iframe."+r.lazyClass+",."+r.lazyBackgroundClass,o={timeout:r.idleLoadTimeout},a=function(e){return[].slice.call(e)},i=function(e){if("IMG"===e.tagName){var t=e.parentNode;"PICTURE"===t.tagName&&a(t.querySelectorAll("source")).forEach(function(e){return s(e)}),s(e)}"VIDEO"===e.tagName&&(a(e.querySelectorAll("source")).forEach(function(e){return s(e)}),s(e),!0===e.autoplay&&e.load()),"IFRAME"===e.tagName&&s(e),e.classList.contains(r.lazyBackgroundClass)&&(e.classList.remove(r.lazyBackgroundClass),e.classList.add(r.lazyBackgroundLoaded))},s=function(e){null!==e.getAttribute("data-srcset")&&e.setAttribute("srcset",e.getAttribute("data-srcset")),null!==e.getAttribute("data-src")&&e.setAttribute("src",e.getAttribute("data-src")),null!==e.getAttribute("data-poster")&&e.setAttribute("poster",e.getAttribute("data-poster"))},l=function yallBack(){var e=!1;!1===e&&u.length>0&&(e=!0,setTimeout(function(){u.forEach(function(e){e.getBoundingClientRect().top<=window.innerHeight+r.threshold&&e.getBoundingClientRect().bottom>=-r.threshold&&"none"!==getComputedStyle(e).display&&(!0===r.idlyLoad&&!0===t.idleCallbackSupport?requestIdleCallback(function(){i(e)},o):i(e),e.classList.remove(r.lazyClass),u=u.filter(function(t){return t!==e}))}),e=!1,0===u.length&&!1===r.observeChanges&&t.eventsToBind.forEach(function(e){return e[0].removeEventListener(e[1],yallBack)})},r.throttleTime))},u=a(document.querySelectorAll(n));if(!0===t.intersectionObserverSupport){var c=new IntersectionObserver(function(e,n){e.forEach(function(e){if(!0===e.isIntersecting||e.intersectionRatio>0){var a=e.target;!0===r.idlyLoad&&!0===t.idleCallbackSupport?requestIdleCallback(function(){return i(a)},o):i(a),a.classList.remove(r.lazyClass),n.unobserve(a),u=u.filter(function(e){return e!==a})}})},{rootMargin:r.threshold+"px 0%"});u.forEach(function(e){return c.observe(e)})}else t.eventsToBind.forEach(function(e){return e[0].addEventListener(e[1],l)}),l();!0===t.mutationObserverSupport&&!0===r.observeChanges&&new MutationObserver(function(e){return e.forEach(function(){a(document.querySelectorAll(n)).forEach(function(e){-1===u.indexOf(e)&&(u.push(e),!0===t.intersectionObserverSupport?c.observe(e):l())})})}).observe(document.querySelector(r.observeRootSelector),r.mutationObserverOptions)}}(); | ||
/*yall.js 2.3.0*/ | ||
var yall=function(){"use strict";return function(e){e||(e={});var t="IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype,n="requestIdleCallback"in window,o=[[document,"scroll"],[document,"touchmove"],[window,"resize"],[window,"orientationchange"]],r=e.lazyClass||"lazy",i=e.lazyBackgroundClass||"lazy-bg",c=e.idleLoadTimeout||100,a=e.threshold||200,s=e.observeChanges||!1,l="img."+r+",video."+r+",iframe."+r+",."+i,u=["srcset","src","poster"],d={timeout:c},f=function(e){return[].slice.call(e)},v=function(t){switch(t.nodeName){case"IMG":var n=t.parentNode;"PICTURE"==n.nodeName&&f(n.querySelectorAll("source")).forEach(function(e){b(e)}),b(t);break;case"VIDEO":f(t.querySelectorAll("source")).forEach(function(e){b(e)}),b(t),t.autoplay&&t.load();break;case"IFRAME":b(t)}t.classList.contains(i)&&(t.classList.remove(i),t.classList.add(e.lazyBackgroundLoaded||"lazy-bg-loaded"))},b=function(e){u.forEach(function(t){t in e.dataset&&(e[t]=e.dataset[t])})},g=function yallBack(){var t=!1;!t&&h.length&&(t=!0,setTimeout(function(){h.forEach(function(e){e.getBoundingClientRect().top<=window.innerHeight+a&&e.getBoundingClientRect().bottom>=-a&&"none"!=getComputedStyle(e).display&&(n&&c?requestIdleCallback(function(){v(e)},d):v(e),e.classList.remove(r),h=h.filter(function(t){return t!=e}))}),t=!1,h.length||s||o.forEach(function(e){e[0].removeEventListener(e[1],yallBack)})},e.throttleTime||200))},h=f(document.querySelectorAll(l));if(/(google|bing|yandex|duckduck)bot/i.test(navigator.userAgent))h.forEach(function(e){v(e)});else{if(t){var m=new IntersectionObserver(function(e,t){e.forEach(function(e){if(e.isIntersecting){var o=e.target;n&&c?requestIdleCallback(function(){v(o)},d):v(o),o.classList.remove(r),t.unobserve(o),h=h.filter(function(e){return e!=o})}})},{rootMargin:a+"px 0%"});h.forEach(function(e){m.observe(e)})}else o.forEach(function(e){e[0].addEventListener(e[1],g)}),g();"MutationObserver"in window&&s&&new MutationObserver(function(e){e.forEach(function(){f(document.querySelectorAll(l)).forEach(function(e){-1==h.indexOf(e)&&(h.push(e),t?m.observe(e):g())})})}).observe(document.querySelector(e.observeRootSelector||"body"),e.mutationObserverOptions||{childList:!0,subtree:!0})}}}(); |
{ | ||
"name": "yall-js", | ||
"version": "2.2.2", | ||
"version": "2.3.0", | ||
"description": "Yet Another Lazy Loader", | ||
"main": "./dist/yall.js", | ||
"module": "./src/yall.mjs", | ||
"jsnext:main": "./src/yall.mjs", | ||
"scripts": { | ||
@@ -15,3 +16,3 @@ "clean": "npx rimraf ./dist", | ||
"type": "git", | ||
"urnl": "git+ssh://git@github.com/malchata/yall.js.git" | ||
"url": "git+ssh://git@github.com/malchata/yall.js.git" | ||
}, | ||
@@ -34,9 +35,9 @@ "keywords": [ | ||
"@babel/cli": "^7.2.3", | ||
"@babel/core": "^7.2.2", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.3.2", | ||
"@babel/preset-env": "^7.3.1", | ||
"eslint": "^5.13.0", | ||
"@babel/core": "^7.3.4", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.3.4", | ||
"@babel/preset-env": "^7.3.4", | ||
"eslint": "^5.15.2", | ||
"express": "^4.16.4", | ||
"rimraf": "^2.6.3", | ||
"rollup": "^1.1.2", | ||
"rollup": "^1.6.0", | ||
"rollup-plugin-babel": "^4.3.2", | ||
@@ -43,0 +44,0 @@ "rollup-plugin-copy": "^0.2.3", |
# yall.js (Yet Another Lazy Loader) | ||
[![Build Status](https://travis-ci.org/malchata/yall.js.svg?branch=master)](https://travis-ci.org/malchata/yall.js) ![](https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?label=Uncompressed) ![](https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?compression=gzip&label=gzip) ![](https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?compression=brotli&label=brotli) | ||
<p align="center"> | ||
<strong>ES5 (.js) version</strong> | ||
</p> | ||
<p align="center"> | ||
<img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?label=Uncompressed" alt="Uncompressed size."> <img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?compression=gzip&label=gzip" alt="gzip size."> <img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.js?compression=brotli&label=brotli" alt="Brotli size."> | ||
</p> | ||
<p align="center"> | ||
<strong>ES6 (.mjs) version</strong> | ||
</p> | ||
<p align="center"> | ||
<img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.mjs?label=Uncompressed" alt="Uncompressed size."> <img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.mjs?compression=gzip&label=gzip" alt="gzip size."> <img src="https://img.badgesize.io/malchata/yall.js/master/dist/yall.min.mjs?compression=brotli&label=brotli" alt="Brotli size."> | ||
</p> | ||
yall.js is a featured-packed script that lazy loads content for `<img>`, `<picture>`, `<video>` and `<iframe>` elements, and can also lazy load CSS background images. It works in all modern browsers including IE11. It uses [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) where available, but falls back to `scroll`, `touchmove`, `resize`, and `orientationchange` events where necessary. It can also monitor the DOM for changes using [Mutation Observer](https://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/) to lazy load media elements that have been appended to the DOM after initial page render, which may be desirable for single page applications. It can also (optionally) optimize use of browser idle time using [`requestIdleCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback). | ||
yall.js is a featured-packed SEO-friendly lazy loader for `<img>`, `<picture>`, `<video>` and `<iframe>` elements, and can also lazy load CSS background images. It works in all modern browsers as well as IE11. It uses [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) where available, but falls back to `scroll`, `touchmove`, `resize`, and `orientationchange` events where necessary. It can also monitor the DOM for changes using [Mutation Observer](https://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/) to lazy load media elements that have been appended to the DOM after initial page render, which may be desirable for single page applications. It can also (optionally) optimize use of browser idle time using [`requestIdleCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback). | ||
@@ -204,4 +215,3 @@ While yall.js has only been offered in the past as a drop-in script, it's now installable as an npm package: | ||
- `throttleTime` (default: `200`): In cases where Intersection Observer isn't available, standard event handlers are used. `throttleTime` allows you to control how often the code within these event handlers fire in milliseconds. | ||
- `idlyLoad` (default: `false`): If set to `true`, `requestIdleCallback` is used to optimize use of browser idle time to limit monopolization of the main thread. _**Notes:** This setting is ignored if set to `true` in a browser that doesn't support `requestIdleCallback`! Additionally, enabling this could cause lazy loading to be delayed significantly more than you might be okay with! This option trades off some degree of seamless lazy loading in favor of optimized use of browser idle time. Test extensively, and consider increasing the `threshold` option if you set this option to `true`!_ | ||
- `idleLoadTimeout` (default: `100`): If `idlyLoad` is set to `true`, this option sets a deadline in milliseconds for `requestIdleCallback` to kick off lazy loading for an element. | ||
- `idleLoadTimeout` (default: `100`): In environments where `requestIdleCallback` is available, this option sets a deadline in milliseconds for `requestIdleCallback` to kick off lazy loading for an element. If this option is set to `0`, `requestIdleCallback` is never called, and lazy loading for the affected element(s) will begin immediately once they're in the viewport. | ||
- `threshold` (default: `200`): The threshold (in pixels) for how far elements need to be within the viewport to begin lazy loading. | ||
@@ -212,5 +222,5 @@ - `observeChanges` (default: `false`): Use a Mutation Observer to examine the DOM for changes. This is useful if you're using yall.js in a single page application and want to lazy load resources for markup injected into the page after initial page render. _**Note:** This option is ignored if set to `true` in a browser that doesn't support Mutation Observer!_ | ||
## Words of wisdom | ||
## Words of advice | ||
yall.js doesn't care about placeholders, and won't try to minimize layout shifting for you. Use appropriate `width` and `height` attributes on elements, as well as lightweight placeholders | ||
It is not yall.js's job to minimize layout shifting for you. Use appropriate `width` and `height` attributes on elements, as well as lightweight placeholders for your images. | ||
@@ -217,0 +227,0 @@ In the case of `<video>`, avoid lazy loading a placeholder with the `data-poster` attribute for autoplaying videos and just use `poster`. On the other hand _do_ consider lazy loading a placeholder image with `data-poster` for non-autoplaying videos. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
239
0
33362
6
331