Lazy loading images is a standard strategy for improving web page performance and user experience. By lazy loading images, a placeholder will be displayed first, and once the element enters user’s viewport, the actual image will be loaded and the placeholder is swapped for the actual image.
Depending on how many images are being loaded outside user’s viewport, this strategy can significantly improve page load time. It is also one of the Google recommended optimization tips for all websites.
Why Background Images?
In today’s article we will show a simple example how to lazy load background images. Background images can be tricky because most lazy loading libraries are designed to work with <img/>
(or picture) tags.
In case you are working with image tags, there are already plenty of great, reusable implementations for various platforms already out there. One might even ask,
Why do you want to load images as backgrounds, why not just switch to using image tags?
The difference comes from the fact that, with background images, you can set CSS properties such as background-size
, background-repeat
and background-position
. These come in especially handy when trying to design consistent looking list views, as is often the case in scenarios where you need to lazy load images in the first place. (You can do this also with newer HTML tags by combining <picture>
, <image>
, and object-fit
property, but that is a story for another article!)
Considerations
Next we will show you a simple example of how to implement this behavior. This example is purposely simplified and you are encouraged to add your own flair to it.
Another point to consider is that this example is designed for pages that load their entire HTML DOM tree up front. If you are using a framework (such as react, vue, or angular) to dynamically load page content, this solution is not a good option for you.
This sample implementation will load an image one time and the image will be visible from that point forward.
Sample Code
This example involves working with 3 files:
index.html
- HTML template with elementsstyle.css
- CSS stylesheetscript.js
- javascript file
This implementation is an adapted version of this example.
index.html
1 | <!-- other elements here --> |
For each element with a background image, add a class name that indicates the background will be lazy loaded. You can choose any class name; in this example we use lazy-background
.
style.css
1 | .image{ |
Use CSS stylesheet to set the element background and other properties for when the special class name lazy-background
is applied, as well as when image is in the viewport. The element is in the viewport if lazy-background
class name is NOT applied.
Feel free to change this CSS to match your style, BUT make sure to disable background-image
when element has lazy-background
class applied to it. Also note you have to use important
to override the inline style attribute.
Next add a reference to your stylesheet to your index.html. When you load the page, you should see the placeholder state and no images.
script.js
1 | document.addEventListener("DOMContentLoaded", function() { |
The above code snippet is responsible for detecting when an element enters the viewport. When this event occurs, the lazy-background
class will be removed from the element, allowing it to load its actual background image.
Lasty, add reference to script.js to index.html. Reload the page and background images should now load automatically once they enter the viewport.
Note that this script queries for all lazy-loadable nodes exactly once immediately after page load. If your page’s DOM tree changes afterwards, you will need to adjust this script to also listen to changes in the DOM tree.
Also note that this loading technique assumes IntersectionObserver
is available and does not handle the case where that assumption is not true. This Web API is widely available, but for those browsers where this API is not available, all images will be loaded normally after page load (see script.js lines 27-30
).
If you are curious about seeing a real-life demo, check out this page.
Happy Coding!