#19 Lazy Loading Images
Saturday, February 23, 2019
In this article we will see how to lazy load all of our image tags. The process will be to add a small npm package to our project and then to update our image tags. The updating is extremely simple and basically boils down to adding a css class and coverting any srcset and src attributes to be data dashed. As we will see this will work for all of our images regardless of whether we are solving either the resolution switching or art direction problems.
Parts
- Part 29: Offset Pager Urls
- Part 28: Offset Pager Start
- Part 27: Mock Context Builder
- Part 26: Mock Repository
- Part 25: Mock Async
- Part 24: Picture Tag Helper
- Part 23: Img DPR Tag Helper
- Part 22: Img Responsive Tag Helper
- Part 21: Img Optimized Display
- Part 20: Img Optimization
- Part 19: Img Lazy Loading
- Part 18: Img Responsive
- Part 17: Bottom Nav
- Part 16: Main Nav Cookie
- Part 15: Main Nav Mobile
- Part 14: Main Nav Search
- Part 13: Main Nav Auth
- Part 12: Main Nav Anchors
- Part 11: Main Nav Logo
- Part 10: Search Results
- Part 9: Search Manager
- Part 8: Search Start
- Part 7: Seeding the Database
- Part 6: Domain Database
- Part 5: Emailing Exceptions
- Part 4: Mailkit
- Part 3: View Renderer
- Part 2: Upgrade to 2.1
- Part 1: Quick Start
Example UI
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
We will just start off by creating all the underlying code for the examples that we will be showing in this article (a). Our goal is to take all of the previous examples and show how to accomplish them while adding lazy loading of our images into the equation.
Responsive-Images.cshtml
...
<nav class="responsive-image-nav">
<label>Problems</label>
...
<a class="@( Model.Problem == "lazy-loading" ? "active" : "" )"
href="/responsive-images?problem=lazy-loading&query=off">Lazy Loading</a>
</nav>
...
else if (Model.Problem == "lazy-loading")
{
<nav class="responsive-image-nav lazy-loading-nav">
<label>Lazy</label>
<a class="@( Model.Query == "off" ? "active" : "" )"
href="/responsive-images?problem=lazy-loading&query=off">Off</a>
<a class="@( Model.Query == "non-responsive" ? "active" : "" )"
href="/responsive-images?problem=lazy-loading&query=non-responsive">Non-Responsive</a>
<a class="@( Model.Query == "different-sizes" ? "active" : "" )"
href="/responsive-images?problem=lazy-loading&query=different-sizes">Different Sizes</a>
<a class="@( Model.Query == "same-size" ? "active" : "" )"
href="/responsive-images?problem=lazy-loading&query=same-size">Same Size</a>
<a class="@( Model.Query == "picture" ? "active" : "" )"
href="/responsive-images?problem=lazy-loading&query=picture">Picture</a>
</nav>
if (Model.Query == "off")
{
for(var i = 1; i <= 10; i++)
{
}
}
else if (Model.Query == "non-responsive")
{
for(var i = 1; i <= 10; i++)
{
}
}
else if (Model.Query == "different-sizes")
{
for(var i = 1; i <= 10; i++)
{
}
}
else if (Model.Query == "same-size")
{
for(var i = 1; i <= 10; i++)
{
}
}
else if (Model.Query == "picture")
{
for(var i = 1; i <= 10; i++)
{
}
}
}
Back to npm
- WebUi
- package.json
To accomplish the lazy loading of our images we are going to make use of an npm package called lazysizes . To add the package we just need to use the command shown in (b) which at the time of the writing of this article will install the package with the version number shown in (c)
Terminal
npm install --save-dev lazysizes
package.json
{
...
"devDependencies": {
...,
"lazysizes": "^4.1.4",
...
}
}
Add lazysizes to our pages
- WebUi
- Source
- main.page.ts
- Source
Now that the package has been downloaded we need to add it to all of our pages. The easiest way to do this is to add it in our main page typescript file (d).
main.page.ts
...
require("lazysizes");
...
First off no lazy loading
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
We will start by seeing how the browser reacts to the inclusion of 10 image tags without any lazy loading functionality being used (e). If we check the network tab as expected all of the images will be loaded on page load regardless of whether or not they are in or near the viewport of the device.
Responsive-Images.cshtml
...
else if (Model.Problem == "lazy-loading")
{
...
if (Model.Query == "off")
{
for(var i = 1; i <= 10; i++)
{
<div class="image-container">
<img src="/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-320w.jpg"
alt="Woman sitting on a chair beside a balloon">
<div class="image-caption">
<p>Photo by Daria Shevtsova from Pexels</p>
<p>https://www.pexels.com/photo/woman-sitting-on-chair-beside-balloon-1391580/</p>
</div>
</div>
}
}
}
Lazy loading a standard image tag
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
Next up we will simply take the image tags that we were loading in the previous example and modify them in such a way to cause lazysizes to lazy load them (f). In this case we just need to add a css class to the image and change the src attribute to data-src. Once those two changes are made lazysizes will take care of requesting the images when/if the user scrolls the page.
Responsive-Images.cshtml
...
else if (Model.Problem == "lazy-loading")
{
...
else if (Model.Query == "non-responsive")
{
for(var i = 1; i <= 10; i++)
{
<div class="image-container">
<img class="lazyload"
data-src="/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-320w.jpg"
alt="Woman sitting on a chair beside a balloon">
<div class="image-caption">
<p>Photo by Daria Shevtsova from Pexels</p>
<p>https://www.pexels.com/photo/woman-sitting-on-chair-beside-balloon-1391580/</p>
</div>
</div>
}
}
}
Different Sizes
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
Adding lazy loading to any of our image tags that are showing the same image at different resolutions is just about as easy except we have three minor changes to make instead of two (g). The changes we make are to add the css class, change the srcset attribute to data-srcset and change the src attribute to data-src.
Responsive-Images.cshtml
...
else if (Model.Problem == "lazy-loading")
{
...
else if (Model.Query == "different-sizes")
{
for(var i = 1; i <= 10; i++)
{
<div class="image-container">
<img class="lazyload"
data-srcset="/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-320w.jpg 320w,
/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-480w.jpg 480w,
/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-800w.jpg 800w"
sizes="(max-width: 320px) 320px,
(max-width: 480px) 480px,
800px"
data-src="/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-800w.jpg"
alt="Woman sitting on a chair beside a balloon">
<div class="image-caption">
<p>Photo by Daria Shevtsova from Pexels</p>
<p>https://www.pexels.com/photo/woman-sitting-on-chair-beside-balloon-1391580/</p>
</div>
</div>
}
}
}
Same Size
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
Following the pattern the next thing to accomplish is to convert our image tags that serve an image based on the device pixel ratio, DPR, of the user's device to also be lazy loaded (h). In this case the way we do that is the exact same way that we do in the different sizes case by adding the class and changing the srcset and src attributes.
Responsive-Images.cshtml
...
else if (Model.Problem == "lazy-loading")
{
...
else if (Model.Query == "same-size")
{
for(var i = 1; i <= 10; i++)
{
<div class="image-container same-size">
<img class="lazyload"
data-srcset="/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-320w.jpg,
/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-640w.jpg 2x"
data-src="/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-640w.jpg"
alt="Woman sitting on a chair beside a balloon">
<div class="image-caption">
<p>Photo by Daria Shevtsova from Pexels</p>
<p>https://www.pexels.com/photo/woman-sitting-on-chair-beside-balloon-1391580/</p>
</div>
</div>
}
}
}
The picture tag
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
Last but not least we need to change the contents of our picture tags to be lazy loaded as well. Thankfully it is just the same pattern over and over. We just need to add the css class to the image tag and change any srcset and src attributes to their data dashed counterparts (i).
Responsive-Images.cshtml
...
else if (Model.Problem == "lazy-loading")
{
...
else if (Model.Query == "picture")
{
for(var i = 1; i <= 10; i++)
{
<div class="image-container">
<picture>
<source media="(max-width: 799px)"
data-srcset="/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-320w.jpg">
<source media="(min-width: 800px)"
data-srcset="/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-800w.jpg">
<img class="lazyload"
data-src="/images/responsive-images/woman-balloon-chair-dark-Copy@(i)-800w.jpg"
alt="Woman sitting on a chair beside a balloon">
</picture>
<div class="image-caption">
<p>Photo by Daria Shevtsova from Pexels</p>
<p>https://www.pexels.com/photo/woman-sitting-on-chair-beside-balloon-1391580/</p>
</div>
</div>
}
}
}