Skip to content

Commit d118cc6

Browse files
committed
Updated README.
1 parent d2c94eb commit d118cc6

File tree

1 file changed

+55
-133
lines changed

1 file changed

+55
-133
lines changed

README.md

+55-133
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
<img src="https://img.badgesize.io/malchata/yall.js/main/dist/yall.min.mjs?label=Uncompressed" alt="Uncompressed size.">&nbsp;<img src="https://img.badgesize.io/malchata/yall.js/main/dist/yall.min.mjs?compression=gzip&label=gzip" alt="gzip size.">&nbsp;<img src="https://img.badgesize.io/malchata/yall.js/main/dist/yall.min.mjs?compression=brotli&label=brotli" alt="Brotli size.">
1414
</p>
1515

16-
**Note: Barring any bugfixes, development of yall.js is done. Additionally, consider using [native lazy loading](https://web.dev/native-lazy-loading/) instead of any JavaScript-based solution unless you need to lazy load resources other than images and iframes.**
17-
18-
yall.js is a featured-packed SEO-friendly lazy loader for `<img>`, `<picture>`, `<video>` and `<iframe>` elements, as well as CSS background images. It works in all modern browsers, including IE 11. It uses [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) where available, but as of version 3, this API must be polyfilled for older browsers. 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 elements that have been appended to the DOM after initial load, which may be desirable for single page applications. It can also optimize use of browser idle time using [`requestIdleCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback), and reduces jank by using [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame).
16+
yall.js is a SEO-friendly lazy loader for `<video>` elements as well as CSS background images. It works in all modern browsers. It uses [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) where available. yall.js 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 elements that have been appended to the DOM after initial load, which may be desirable for single page applications.
1917

2018
To use yall, grab `yall.min.js` (or `yall.min.mjs` if you're the modern sort) from the `dist` directory and slap it on your page. You can also install it with npm:
2119

@@ -28,61 +26,27 @@ npm install yall-js
2826
This is version 3 of yall.js, and introduces breaking changes over all prior versions. This is simplest way to initialize yall.js:
2927

3028
```javascript
31-
document.addEventListener("DOMContentLoaded", yall);
29+
// Import y'all
30+
import { yall } from "yall-js";
31+
32+
// Invoke!
33+
yall();
3234
```
3335

3436
The above syntax is sufficient if you don't want to pass in any options. [If you _do_ want to specify options](#api-options), you'll need to use a slightly more verbose syntax:
3537

3638
```javascript
37-
document.addEventListener("DOMContentLoaded", function() {
38-
yall({
39-
observeChanges: true
40-
});
41-
});
42-
```
39+
// Import y'all
40+
import { yall } from "yall-js";
4341

44-
Unlike version 2 which provided a fallback for browsers without `IntersectionObserver` support, version 3 doesn't. If you need to support browsers that don't support `IntersectionObserver`, you can conditionally polyfill this feature through [polyfill.io](https://polyfill.io/) like so:
45-
46-
```html
47-
<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
42+
// Invoke!
43+
yall({
44+
observeChanges: true
45+
});
4846
```
4947

5048
From there, lazy loading elements depends on _what_ you want to lazy load. Let's take a look at what you can do with it.
5149

52-
### `<img>`
53-
54-
Here's a typical `<img>` element use case:
55-
56-
```html
57-
<!-- An src-only <img> element example -->
58-
<img class="lazy" src="placeholder.jpg" data-src="image-to-lazy-load.jpg" alt="Alternative text to describe image.">
59-
```
60-
61-
Here, we specify an optional placeholder image in the `src` attribute, and point to the image we want to lazy load in the `data-src` attribute. Attaching a `class` of `lazy` exposes elements to yall.js, and is necessary for the lazy loader to work (although this class can be overridden in the options). Let's look at an example using both `src` and `srcset`:
62-
63-
```html
64-
<!-- A somewhat more complex src + srcset example -->
65-
<img class="lazy" src="placeholder.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" data-src="image-to-lazy-load-1x.jpg" alt="Alternative text to describe image.">
66-
```
67-
68-
Mostly the same as before, just another `data-` attributes for `srcset` is all.
69-
70-
**Note:** If you're using `media` and `sizes` attributes, _do not_ prefix them with `data-`. Leave them as-is.
71-
72-
### `<picture>`
73-
74-
Since `<picture>` is a thing, yall.js supports that, too:
75-
76-
```html
77-
<!-- A more complex <picture> + <img> + src/srcset example -->
78-
<picture>
79-
<source data-srcset="image-to-lazy-load-2x.webp 2x, image-to-lazy-load-1x.webp 1x" type="image/webp">
80-
<img class="lazy" src="placeholder.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" data-src="image-to-lazy-load-1x.jpg" alt="Alternative text to describe image.">
81-
</picture>
82-
```
83-
84-
Not too much different than the `<img>` use cases, except you're pointing to the images you want to load in the `<source>` element(s) as well as the `<img>` element.
85-
8650
### `<video>`
8751

8852
yall.js covers two possible lazy loading patterns for video.
@@ -119,14 +83,6 @@ This pattern is slightly different than the one before it. Because we're not try
11983

12084
**Note:** For the sake of your users, don't mix the above markup patterns. If a video is going to use `autoplay` to replace an animated image, lazy loading a placeholder image via `data-poster` isn't necessary. Furthermore, if you're unsure of what to do, _let browsers handle this stuff and don't use yall.js to manage loading of videos at all!_
12185

122-
### `<iframe>`
123-
124-
You can also lazy load `<iframe>`s:
125-
126-
```html
127-
<iframe class="lazy" data-src="some-other-document.html"></iframe>
128-
```
129-
13086
### CSS images
13187

13288
Last, but not least, you can use yall.js to lazy load images referenced in CSS. This might be useful if you have a very large `background-image` you'd like to defer. Proper use of this feature requires _both_ HTML and CSS. To start, let's say you have a `<div>` that loads a very large masthead `background-image`:
@@ -159,40 +115,28 @@ This works because, unlike HTML which loads most resources regardless of their v
159115
Slap on some `<noscript>`:
160116

161117
```html
162-
<!-- A <noscript> example using <img> with src and srcset. -->
163-
<img class="lazy" data-srcset="/img/image-to-lazy-load-2x.jpg 2x, /img/image-to-lazy-load-1x.jpg 1x" data-src="/img/image-to-lazy-load-1x.jpg" src="/img/placeholder.jpg" alt="Alternative text to describe image.">
164-
<noscript>
165-
<img srcset="/img/image-to-lazy-load-2x.jpg 2x, /img/image-to-lazy-load-1x.jpg 1x" src="/img/image-to-lazy-load-1x.jpg" alt="Alternative text to describe image.">
166-
</noscript>
167-
168-
<!-- And a <picture> example. -->
169-
<picture>
170-
<source data-srcset="/img/image-to-lazy-load-2x.webp 2x, /img/image-to-lazy-load-1x.webp 1x" type="image/webp">
171-
<img class="lazy" data-srcset="/img/image-to-lazy-load-2x.jpg 2x, /img/image-to-lazy-load-1x.jpg 1x" data-src="/img/image-to-lazy-load-1x.jpg" src="/img/placeholder.jpg" alt="Alternative text to describe image.">
172-
</picture>
173-
<noscript>
174-
<picture>
175-
<source srcset="/img/image-to-lazy-load-2x.webp 2x, /img/image-to-lazy-load-1x.webp 1x" type="image/webp">
176-
<img srcset="/img/image-to-lazy-load-2x.jpg 2x, /img/image-to-lazy-load-1x.jpg 1x" src="/img/image-to-lazy-load-1x.jpg" alt="Alternative text to describe image.">
177-
</picture>
178-
</noscript>
179-
180-
<!-- Here's a <video> example, too. -->
181-
<video class="lazy" autoplay loop muted playsinline>
118+
<!-- A `<video>` example: -->
119+
<video class="lazy" preload="none" autoplay loop muted playsinline>
182120
<source data-src="video.webm" type="video/webm">
183121
<source data-src="video.mp4" type="video/mp4">
184122
</video>
185123
<noscript>
186-
<video autoplay loop muted playsinline>
124+
<video preload="none" autoplay loop muted playsinline>
187125
<source src="video.webm" type="video/webm">
188126
<source src="video.mp4" type="video/mp4">
189127
</video>
190128
</noscript>
191129

192-
<!-- Here's an <iframe> example for good measure. -->
193-
<iframe class="lazy" data-src="lazy.html"></iframe>
130+
<!-- A `<video>` example: -->
131+
<video class="lazy" preload="none" autoplay loop muted playsinline data-poster="img/video-poster.jpg">
132+
<source src="video.webm" type="video/webm">
133+
<source src="video.mp4" type="video/mp4">
134+
</video>
194135
<noscript>
195-
<iframe src="lazy.html"></iframe>
136+
<video preload="none" autoplay loop muted playsinline poster="img/video-poster.jpg">
137+
<source src="video.webm" type="video/webm">
138+
<source src="video.mp4" type="video/mp4">
139+
</video>
196140
</noscript>
197141
```
198142

@@ -239,11 +183,6 @@ The element class used by yall.js to find elements to lazy load CSS background i
239183
**default:** `"lazy-bg-loaded"`<br>
240184
When yall.js finds elements using the class specified by `lazyBackgroundClass`, it will remove that class and put this one in its place. This will be the class you use in your CSS to bring in your background image when the affected element is scrolled into the viewport.
241185

242-
### `idleLoadTimeout`
243-
244-
**default:** `200`<br>
245-
In environments where `requestIdleCallback` is available, this option sets a deadline in milliseconds to kick off lazy loading for elements. If this is set to `0`, `requestIdleCallback` is never called, and lazy loading for elements will begin immediately once they're in the viewport.
246-
247186
### `threshold`
248187

249188
**default:** `200`<br>
@@ -254,35 +193,33 @@ The threshold (in pixels) for how far elements need to be within the viewport to
254193
An object of events that get sent directly to [`addEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) for each element to be lazy loaded. Rather than building an opinionated, bespoke event management system, this system gets out of your way and lets you to specify whatever events are possible to bind with `addEventListener`. Here's an example below:
255194

256195
```javascript
257-
document.addEventListener("DOMContentLoaded", function () {
258-
yall({
259-
events: {
260-
// The object key is sent as the first argument to `addEventListener`,
261-
// which is the event. The corresponding value can be the callback if you
262-
// don't want to send any options to `addEventListener`.
263-
load: function (event) {
264-
if (!event.target.classList.contains("lazy") && event.target.nodeName == "IMG") {
265-
event.target.classList.add("yall-loaded");
196+
yall({
197+
events: {
198+
// The object key is sent as the first argument to `addEventListener`,
199+
// which is the event. The corresponding value can be the callback if you
200+
// don't want to send any options to `addEventListener`.
201+
load: function (event) {
202+
if (!event.target.classList.contains("lazy")) {
203+
event.target.classList.add("yall-loaded");
204+
}
205+
},
206+
// If we want to pass options to the third argument in `addEventListener`,
207+
// we can use a nested object syntax like so:
208+
error: {
209+
// Here, the `listener` member is the callback.
210+
listener: function (event) {
211+
if (!event.target.classList.contains("lazy") && event.target.nodeName == "VIDEO") {
212+
event.target.classList.add("yall-error");
266213
}
267214
},
268-
// If we want to pass options to the third argument in `addEventListener`,
269-
// we can use a nested object syntax like so:
270-
error: {
271-
// Here, the `listener` member is the callback.
272-
listener: function (event) {
273-
if (!event.target.classList.contains("lazy") && event.target.nodeName == "IMG") {
274-
event.target.classList.add("yall-error");
275-
}
276-
},
277-
// The option below is sent as the third argument to `addEventListener`,
278-
// offering more control over how events are bound. If you want to
279-
// specify `useCapture` in lieu of options pass a boolean here instead.
280-
options: {
281-
once: true
282-
}
215+
// The option below is sent as the third argument to `addEventListener`,
216+
// offering more control over how events are bound. If you want to
217+
// specify `useCapture` in lieu of options pass a boolean here instead.
218+
options: {
219+
once: true
283220
}
284221
}
285-
});
222+
}
286223
});
287224
```
288225

@@ -305,35 +242,20 @@ If `observeChanges` is set to `true`, the value of this string is fed into `docu
305242
**default:** `{ childList: true, subtree: true }`<br>
306243
Options to pass to the `MutationObserver` instance. Read [this MDN guide](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver#MutationObserverInit) for a list of options. It's very possible that changing this value could result in yall.js failing to lazy load resources that are appended to the DOM later on.
307244

308-
### `noPolyfill`
309-
310-
**default:** false
311-
If `noPolyfill` is set to `true` yall.js will assume you are not polyfilling `IntersectionObserver`, and will subsequently load all resources when it detects no support for `IntersectionObserver`. This option will save you ~2.4kB for the `intersection-observer` polyfill, but be advised that invoking this option means that you could potentially load both placeholders _and_ the final image sources. Additionally, you'll be dependent on JavaScript to trigger immediate loading of all images in the document for browsers that don't support `IntersectionObserver`. For these reasons, it's only advised to enable this option if the vast majority of your users are on browsers that support `IntersectionObserver`.
312-
313245
## Words of advice
314246

315-
This script aims to provide a reasonable level of compatibility down to IE 11, but as stated previously, you will need to polyfill `IntersectionObserver` for yall.js to work in that browser. If you don't polyfill `IntersectionObserver`, non-supporting browsers won't throw an error, they'll fail silently. However, features that are natively available in at least IE 11 (such as `MutationObserver` and `requestAnimationFrame` will not be checked for, and _will_ throw errors if they are not available. For example, because `requestIdleCallback` is not available in IE 11, it _will_ be checked for. If it doesn't exist, it will simply not be used. Polyfill it if you need it.
247+
Unlike previous versions of yall-js, compatibility back to IE 11 is no longer a goal. If you need compatibility with older browsers, install the previous release of yall.js like so:
316248

317-
Also, it is not this script's job to minimize layout shifting for you. [Use appropriate `width` and `height` attributes](https://www.smashingmagazine.com/2020/03/setting-height-width-images-important-again/), styles, and lightweight placeholders for your images.
318-
319-
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. Or you can opt _not_ to use a `poster` image. Your website, your call.
320-
321-
Also, do _not_ lazy load resources that are likely to near the top of the page&mdash;or "above the fold", as it were. Doing so is an anti-pattern in that those resources will not begin loading until yall.js has been loaded, which may take much longer than if those resources were loaded normally.
249+
```shell
250+
npm i yall@3.2.0
251+
```
322252

323-
## Integration
253+
Also, it is not this script's job to minimize [layout shifts](https://web.dev/cls/) for you. [Use appropriate `width` and `height` attributes](https://www.smashingmagazine.com/2020/03/setting-height-width-images-important-again/), styles, and lightweight placeholders for your images.
324254

325-
Here are some external libraries or extensions built on top `malchata/yall.js`.
255+
For `<video>` elements, 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. Or you can opt _not_ to use a `poster` image. Your website, your call.
326256

327-
- [`adhocore/twig-yall`](https://github.com/adhocore/twig-yall) - A twig template engine extension that makes integration of `malchata/yall.js` a breeze.
257+
Also, do _not_ lazy load resources that are likely to near the top of the page&mdash;or "above the fold", as it were. Doing so is an anti-pattern in that those resources will not begin loading until yall.js has been loaded, which may take much longer than if those resources were loaded normally. Such a pattern will negatively affect your page's [LCP](https://web.dev/lcp/).
328258

329259
## Contributing
330260

331-
Please read the [contribution guidelines](https://github.com/malchata/yall.js/blob/master/CONTRIBUTING.md). If you think I'm some kind of grumpy crank after reading that, please remember that this is a hobby project you can use for free. Here's a couple other options for you if yall.js doesn't do what you need it to:
332-
333-
- [Lozad.js](https://github.com/ApoorvSaxena/lozad.js)
334-
- [lazysizes](https://github.com/aFarkas/lazysizes)
335-
336-
## Special thanks
337-
338-
Thank you to [BrowserStack](https://www.browserstack.com/) for graciously providing free cross-platform browser testing services!
339-
[![BrowserStack](https://res.cloudinary.com/drp9iwjqz/image/upload/f_auto,q_auto/v1527175969/browserstack_txnmf8.png)](https://www.browserstack.com/)
261+
Please read the [contribution guidelines](https://github.com/malchata/yall.js/blob/master/CONTRIBUTING.md). If you think I'm some kind of grumpy crank after reading that, please remember that this is a hobby project you can use for free.

0 commit comments

Comments
 (0)