Skip to content

Instantly share code, notes, and snippets.

@fabiosantoscode
Last active November 6, 2018 09:44
Show Gist options
  • Save fabiosantoscode/8fbdaf244425040050ba to your computer and use it in GitHub Desktop.
Save fabiosantoscode/8fbdaf244425040050ba to your computer and use it in GitHub Desktop.
A new, no-javascript, accessible and performant way to implement lazy loading of images on the web

img[lazy]

This is a proposal to extend HTML to provide a new way to implement lazy-loading images on the web.

Motivation

The ever-growing mass of mobile devices, with tiny screens and limited processing power, are unable to access the web at decent speeds and reasonable prices. Old browsers die hard, and it gets harder and harder to cater to their every need. It is very, very hard, as a web developer, to cater to both mobile browsers and ancient browsers, especially when it comes to those problems which cannot ever have a permanent, one-size-fix-all solution: sticky headers, footers that don't float awkwardly when there's not enough content on the page, and lazyly loaded images. Sticky headers are getting their permanent, one-size-fix-all solution through the position:sticky proposal. Footers are slowly being replaced with taller footers, and infinite scroll, which is a growing trend, makes them disappear from designers' canvases. A problem that's not truly solved is lazy-loaded images.

Lazy-loading images is obviously important when there are lots of images on the page. But it is also crucial in the mobile environment. When a user is not on a wifi connection, it is unfair to make them waste their money downloading images they might never see. Also, since there is a limited amount of parallel requests that can be made at any time, it is best to avoid loading too many images up front, to prevent queuing of future asynchronous requests for more resources.

Because it has so many advantages, you'd expect it to be implemented in a considerable part of the web, using JavaScript. Unfortunately, that is not the case. The reason for that is that it's a non-trivial and error-prone feature to implement, and that there are several major drawbacks in accessibility, semantics, SEO, and performance.

Proposal

I propose a new attribute, lazy, and a matching boolean property in the DOM interface, to be added to the img and picture elements, which will indicate that said img or picture represents an image that is not important to start downloading as the page loads, but instead only when they are inside the viewport, or deemed to be in the viewport soon.

Some examples:

<img src="image.jpg" lazy>
<img srcset="image.jpg, image-high-res.jpg 2x" lazy>
<picture lazy>
   <source srcset="image.jpg" media="(min-width: 500px)">
   <img src="image.jpg">
</picture>

<script>
    var img = document.createElement('img');
    img.src = 'image.jpg';
    img.lazy = true;
    document.body.appendChild(img);
</script>

The problems with the current options

Currently, using javascript, there are many ways to lazy-load an image. There are hundreds of libraries, scripts and examples, to be found online, and it can be implemented by hand. Some of them are written by very smart people who are passionate about the web, but even those will always impose some constraints, because of the way that the web platform works.

  1. They make you drop the [src] attribute. This is because there is no way to stop images (those that are present in the HTML when the page first loads) from downloading using javascript.
  2. You can't show images when javascript is not available (or has crashed). You can indeed copy your image, this time with a [src] attribute, into a <noscript> section, but this is very verbose and does not work when javascript has crashed.
  3. They need to register scroll event handlers, which are CPU-intensive, being even more expensive on mobile browsers (and in smooth scroll situations in desktop browsers) where they usually fire once for every pixel scrolled.
  4. They don't work well with the printing function of the browser
  5. They either use mutation events, make you call a function on every image that is inserted on the DOM, or don't lazy load dynamically inserted images
  6. They have no way of lazy-loading images that slide into the viewport using CSS animations or javascript.

Each and every one of these problems is solved by the lazy attribute.

Conclusion

It's not that the available javascript libraries are not good enough. The problem is that they are limited by the capabilities of the browser platform, so they will never be able to fix them completely and reliably.

I sincerely hope that this attribute can be a solution to the lazy-loading in the future, because without a complete and reliable solution which is easy to use and does not have so many drawbacks, traps and unreasonable tradeoffs, web developers can't be expected to implement and maintain lazy-loading to its fullest potential.

@mariomc
Copy link

mariomc commented Oct 13, 2015

Position sticky :P

@fabiosantoscode
Copy link
Author

Thanks :)

@andrewaguiar
Copy link

⭐ nice proposal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment