Native lazy-loading of images with zero Javascript
Tags: html, webdev, beginners, javascript
Published: 2021-02-08 12:04:18


# About lazy-loading and why you should use it

The worldwide web has evolved over the past decades and today's websites consist not only of text and color, but also of countless media content. First and foremost images.

```html
<img src="/path/to/your/image.jpg" alt="Awesome image" />
```

**But what does this have to do with lazy-loading?**

> Lazy-loading is a technique that defers loading of non-critical resources at page load time. Instead, these non-critical resources are loaded at the moment of need. Where images are concerned, "non-critical" is often synonymous with "off-screen".
> -- <cite>from [web.dev/lazy-loading](https://web.dev/lazy-loading/ "Use lazy-loading to improve loading speed") written by Jeremy Wagner and Rachel Andrew</cite>

This means by using lazy-loading we achieve the following benefits over the classic embedding in HTML:

* **Performance Gains** - With lazy-loading we can improve loading speed by reducing the number of images that need to be loaded initially.
* **Cost reduction** - A lazy loaded image may never need to load because the user never reaches the image's position on the page.

Ok, sounds good. How can we make that happen? What do we need for this? Let's get started!

# The old (Javascript) approach

There are a lot of snippets and scripts like [vanilla-lazyload](https://github.com/verlok/vanilla-lazyload "Library for lazy-loading in plain Javascript at Github") out there that enable lazy-loading via javascript. In almost all cases a data attribute is used to prevent upfront image loading.

``` html
<img data-src="/path/to/your/image.jpg" alt="Awesome image" />
```
But how is the image loaded at all? To achieve this, one of the following two techniques is usually used.

**Event listeners**

This technique uses event listeners on the scroll, resize and orientationChange events in the browser. If one of the mentioned events is fired and assuming the image enters the viewport the data-src attribute is replaced with the src attribute to trigger the loading call. See it in action:

{% codepen https://codepen.io/imagekit_io/pen/MBNwKB %}

**Intersection Observer API**

Unlike the first method, the image is observed (asynchronously) by using the [IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API "MDN Documentation on Intersection Observer API"). The image is then loaded by changing the `data-src` to `src` attribute as soon as it enters the viewport.

{% codepen https://codepen.io/imagekit_io/pen/BPXQZZ %}

But what if I told you that you don't need Javascript at all? 😲 Yes, you heard right! Zero Javascript.

# The new (HTML) approach

So what does this new way of lazy-loading look like? No worries, it's perfectly simple. You just have to add `loading="lazy"` to your image tag and that's it. 😎

```html
<img src="/path/to/your/image.jpg" loading="lazy" />
```
With this new loading attribute, you can completely defer the loading of offscreen images (and even iframes in some browsers) to when they enter the viewport. Enough talking, let's see it in action!

{% codepen https://codepen.io/pfacklam/pen/eYBmeyx %}

The attribute comes with three values:

* **auto** - (Default) equal to not including the attribute.
* **lazy** - Defer loading of resources until it enters the viewport.
* **eager** - Load the resource immediately

**What about browser support?**

The attribute is supported by almost every popular browser (Chrome, Edge, Opera and Firefox). The implementation for Safari is in [progress and almost done](https://bugs.webkit.org/show_bug.cgi?id=200764 "Bug: Main implementation for lazy image loading at webkit"). If you need more detailed information on cross-browser support [caniuse.com](https://caniuse.com/loading-lazy-attr "Information on cross-browser support for loading attribute at caniuse") is your friend. 

**What happens if a browser does not support the attribute?**

Browsers that do not support the loading attribute simply ignore it without any side-effects. Fortunately, there is a polyfill at Github available named [loading-attribute-polyfill](https://github.com/mfranzke/loading-attribute-polyfill "Polyfill for loading attribute at Github") which can be used in those cases.

```javascript
if ('loading' in HTMLImageElement.prototype) {
    // Cool! The browser supports the loading attribute
} else {
   // Houston... We need a polyfill!
}
```

**Are there any limitations?**

Even though it is pretty cool to let the browser do the lazy-loading work, you should be aware of some limitations that come into play when using the attribute:

* Unlike the Javascript variants, you do not have any influence on the threshold to load the resource. It is part of the browser code and can't be changed for now.
* The attribute can't be used in combination with CSS background images. Maybe it will come in near future but it is definitely not available now.
* If printing the webpage is a real usecase for you, then please notice that there is an [open bug](https://bugs.chromium.org/p/chromium/issues/detail?id=875403 "Issue 875403: LazyLoad at chromium") for the loading attribute.

If you liked this post, please give me a ❤️ or even a 🦄 and feel free to follow me on `dev.to`. Appreciate it! ✌️

{% user pfacklam %}