-: One of the most important things
when building any website is performance.
And images have by far the biggest impact on page loading.
And so it's very important
that images are optimized on any page.
And for that,
we can use a strategy called Lazy Loading Images.
So, let me show you now
how to implement that strategy in JavaScript.
And the effect that I'm talking about is this one.
So what for what happens with the images
in this section here?
So you see, as we approach it,
it basically starts to load and then once it finished,
it will get displayed and that placeholder
which is there in the beginning gets replaced.
So you see that?
So let me quickly show you in the HTML how we implement that
and we're actually already here.
So, it's these features here
and so each of these features has an image.
So, the main ingredient to this lazy loading strategy
is that we have a very low resolution image,
which is really small and which is loaded,
right in the beginning.
So that's this image here, and you'll see
that the dimensions are only 200 times 120 in this case.
So let's actually take a look at that image here.
And so, you see it's really small
and it's only 16 kilobytes while the real one,
so this one called digital, is almost half a megabyte.
So that's a huge difference
and that image we then reference here
in this data-src attribute.
So that's a special attribute that we can use,
but any other would work as well.
So this is not a standard HTML attribute
but instead it's one of these special data attributes
that we can do ourselves.
And so basically the idea is to...
As we scroll to one of these low resolution images
we will then replace this low resolution image
with the one that is here specified
in the data-src attribute.
And we then also are gonna remove this class here
which has kind of this filter,
which makes this image blurred because without this filter,
let me show that to you,
without this, it would look really terrible.
So too small to change this now here.
Okay, but let's just remove it here for a second,
just so you can see what it looks like.
And so, maybe you can see, or maybe it's too small
but notice that it's like really pixelated and really ugly.
And so, I created this filter basically,
and so it makes it look like this.
So it hides the fact that it is actually way too small
for its size.
So let's put it back here.
And so this is what this class looks like.
It's simply a blur filter.
And so modern CSS allows us to do this really cool effect.
So, let's implement this and that's actually not too hard
using the Intersection Observer API, one more time.
So lazy loading images and so once again,
this one is really great for performance
while the other things we did so far are more visual things.
This one really impacts how your site works and especially
for your users who might have a slow internet connection
or a low data plan or a slow cell phone.
And we always have to think about these users as well.
Not everyone has a super high end computer
or the latest phone.
Anyway, let's start by selecting our images,
let's call them image targets.
And this selector is gonna be
a little bit different this time
because we don't want to select all the images.
So, we could simply do a selector of image
and that would then give us all the images.
But however not all of them are gonna be lazy loaded,
for example, this one here,
or we have some down here somewhere.
So these avatars here or even this logo,
so these are not lazy loaded.
And so, the ones that will be lazy loaded
are the ones that have this attribute here.
So, this data-src attribute
because that's where we specified
the real high resolution picture.
And so we can actually select four elements
which contain this property.
So if you're familiar with CSS,
maybe you know how to do that
but in case you're not, this is how it works.
So we select all the images which have
the property of data-src.
And that's it.
So, let's check that just to be sure
so that it's gonna work.
And so, indeed here we have these three images
and nothing else.
Then let's create our image observer
and so this is not always the same.
Here's our callback function,
which I'm gonna call load image in a second
and then all options.
And now, let's attach this image observer here basically
to all these targets.
So I'm gonna loop one more time over our targets
just like we did with this section previously.
And this time, let's actually use an arrow function
because all we want to do is to use the image observer
that we created previously to observe each image.
Now let's create that callback function
here also pretty fast.
So it gets the entries and also the observer.
Okay, that's always starting
with the options here and again,
the route set to the entire viewport
and let's start with the threshold at zero,
and then we can adjust it as we go.
But what matters really here is a disc callback function.
So as always, this is where our functionality is.
And so again, we have only one threshold, so only one entry.
So I'm getting that tier.
and now, let's check out actually this entry.
So here we already got three of them,
but all of them are not yet intersecting.
Well, actually it says that this one is,
well, but it isn't really because it's down here.
So, that's a bit weird.
Oh, but of course this still comes from the sections.
So this is still coming from up here somewhere.
Okay, let's delete it here from the sections.
And now, let's see if it's working
and now it is indeed an image.
Now, it appeared a little bit before
and that's because remember that our sections
are actually a little bit shifted
because of this hidden class that we added to them,
they are shifted 8rem down.
So remember that from here.
Let's see.
Yeah, so because of this translate here,
they have moved 8rem down.
And so, then therefore,
this event will fire a little bit early
but that's not a problem at all.
What matters is that the event fired correctly
and that it is indeed intersecting.
Let's just clear it here to wait for the next ones.
And so, here you get to the next one already.
And so, that is indeed this next lazy image here.
And then the next one here as well.
So this one, okay.
And then, as we're moving out of them,
then we get even more
because now they are no longer intersecting.
And so once again,
we need to only do something
if they are actually intersecting.
So we're gonna use the same guard clause as before.
So if they are not intersecting,
then we want an early return.
But otherwise we now want to replace the src attribute
with the data.src.
So as we reach the image,
it's finally time to replace the placeholder image,
which is at the src,
with the one we actually want, which is data-src.
So just like before, each of these images here
is at target or actually at entry.target
So that's the element that's currently being intersected
and then .src= entry.target.dataset.
Remember, that's where these special data properties
are stored and then .src from there.
So this is already the main functionality right here.
So let's try that, but you will not really see it happening
because there's still this blurry filter here on top.
But if we inspect it now, we should already see
that the src is now actually already the original image.
So you see it that it's the really big one
while the other ones are still the lazy ones.
Well, at least this one, the second one,
is already also the original one
because it's already in the viewport two.
So, that's great, that's working just fine.
Now, all we need to do is to then remove that class
that has this blurred filter.
So, that's the lazy image class.
Now, how do we do that?
Well, it's a little bit tricky
because this replacing of the src attribute
actually basically happens behind the scenes.
So JavaScript finds the new image
that it should load and display here.
And it does that behind the scenes.
And once it's finished loading that image
it will emit the load event.
And the load event is just like any other event.
And so we can just listen for it
and then do something so on that image.
So on that image, so that's entry.target,
we can do, addEventListener, and listen for the load event.
And actually, let me show you why it is important
that we do this.
So let's say that we removed
that lazy image class right away.
So entry.target.classList.remove lazy-img.
Let's scroll up here, reload.
And then, well, in this case, the loading happens so fast
that we don't even see a problem.
Maybe we can change that here in the network tab.
So this is a completely new tab
but what we can do here is to simulate or speed.
So this is a bit too big here, actually, I guess.
So I'm not used to the size,
Let me make it a little bit smaller.
So let's change the tier to fast or to slow 3G.
And maybe then, we can see what happens.
So it's not faking that these images
are loading really slow.
So did you see them here blurred now?
So it's really blurred, you see,
but we already removed the filter.
And so, here you can see how the image
is loading basically in the background.
And so it's doing that really slow now
because we said that we are on a slow network here
and now you see it's finished here
and now the original image is being displayed.
So, hopefully you could see that.
I'm not sure if the resolution
of the video is gonna be good enough to see it
but I did for sure see it.
And tear actually now the same as happening.
Let me increase the size of the window a bit, maybe.
So you see it's pretty blurred
but once it's gonna be finished you will then see the final
and beautiful version showing up here.
All right, so we're gonna come back
to this network tab later when we start loading data
from remote sources on the internet.
So this is a very important top in browser tools
but for now, it's also nice
to see the images loading over time behind the scenes.
Well, it's taking a lot of time
so let me just go back to the code here.
And so yeah, now it's finished actually.
And so by the time this loading finishes
it will emit this load event.
And so it is best to then only remove
that blurry filter once that's done.
So it's loading again very slow now
and you see that now it keeps being blurred
and it will only disappear
once the image is in fact loaded.
So I'm not gonna wait for that
because it seems like it's gonna take forever.
Oh, actually it's already done here.
And so, you'll see now the image is downloading
and at the same time the filter appeared
or actually disappeared.
Let's set it back to online.
And so now all of it happens basically at the same time
because we are working on our local development machine.
And so there of course the image
basically arrives instantaneously.
Now as a last step, we can just, as we did before
stop observing these images because it's no longer necessary
we already did our task of loading.
And so we no longer need this.
So entry.target and that's it.
So I hope that with this video,
I could convince you that it's really important
to implement this kind of functionality into your own sites.
So, all you really need to do
is to generate these placeholder images
and blurred them a little bit
and then implement this kind of logic,
which really shouldn't be too much work.
Let me just get rid of this console.log here.
That's a loaded again, because actually we want probably
to load the images a little bit
before we actually reached them.
So ideally we don't want our users to notice
that we are lazy loading these images
So all of this should basically happen
in the background without our user noticing that.
And so we should probably make these
images load a little bit earlier.
So to do that, we can again,
specify a negative root margin here.
So root margin of let's say minus 200 pixels.
And so this is just the same
as we did previously here with the navigation.
So to make the navigation load a little bit
before the threshold was actually reached
and here we are doing the same
so exactly 200 pixels before any of the images is loaded.
It should already start loading.
And by doing that we don't see any delay
in loading when we browse the page.
Well, actually that didn't quite work.
Maybe it should be plus 200.
So as you see, this is all a matter
of trying out and figuring out as we go here.
And so now indeed, as we approached the images,
they're already fully loaded.
So now that happens 200 pixels before we reach them.
And with that, our functionality here is complete
and we are now indeed almost finished with this project.
All that's left to implement is really this slider.
So this component here.
And so that is what we're gonna do in the next video.