- Hello and welcome. My name is Kevin. And in this video, we are
going to be looking at how we can use Intersection Observers to do this thing with
the navigation where, you know when you scroll
down and it shifts from being like transparent to adding a background color to it or something else like that and back off. And we're gonna be sort of
pushing it a little bit, so we're gonna be using
Intersection Observer to do this 'cause it's just more performant than using event listeners on scroll. But we're also gonna
be using CSS variables to make this really easy and fast switch between one state to the other. So you don't actually have to, there's almost not much
CSS that you have to write when it comes to the change state. CSS variables just make that
so easy and awesome to do. So let's go and see how we can do that. (gentle melodic percussion) Okay, so here we are in the S code. And here we have already
set some stuff up, and this starting file
is linked down below. There's one to a GitHub repo
that has this starting file so if you want to follow along. And there is one to the
finished files as well. So if you run into any
trouble and you want to see the exact code I had, you can check out that. What's happening now is
we have this page that, it looks, I think, pretty
nice here at the top. Let's just make this a
bit bigger so we can see what it would look like. So here's sort of where we'd have a logo, our main navigation, and this other little secondary navigation on the side there. And it looks really nice. We have a transparent background on it. But once we get to here, we
can't read the text anymore, and that sucks. And it's nice to have
these fixed navigations, but that switch when we
get to a lower point, and Intersection Observer is really good to be able to do that. So what I've done is I've
created some classes already. So if I come here and I
do class is nav-scrolled and I save that, you're gonna see that we
get the white background with the black text and
everything like that. Just really, really fast, we come and look at my Sass file here. Oh, and really, really fast, you can see I'm
auto-refreshing when I save. If you do use my GitHub repo, there's a readme there that
has really basic instructions on how to use it. I'm using gulp to auto-refresh
and compile my Sass. So there is a little bit of Sass. But what I've done is I've created some custom properties here. And the reason that custom properties are really, really nice
for something like this is I'm changing colors in
a bunch of places at once, but I only have to worry about this and not all the different places that it's actually changing. Now if you don't know
about custom properties, I do have a little miniseries. There should be a card
popping up for that now. But in that series, and in most tutorials you
see on custom properties, they are put on the root instead of inside ofan actual component like I'm doing here in my header. The reason I'm doing it
in my header is because I'm sort of isolating
these colors and these, like the text,
text-inverse, and background are for this header only and I wouldn't be using
them outside of that. If it's something where
you're using the colors throughout your entire site, this doesn't make much sense. But since, for this really basic demo, I'm self-contained colors, pretty much, I've put them in the header. And I think that you can
use them well in that way. And that means anything inside
my header does inherit these. So that's what I'm actually
using on my button. When I'm hovering on that, I'm using my text-inverse
for the text color there and the same thing here on this button. So if we go and look, I'm using it here. So you can see I've set my
background color to background and my color to text. But if we scroll further down here, ♪ Do, do, do ♪ you will find here I have my
hover where I'm switching it so my background has become my text color, my color has become my text-inverse, and I'm just making sure
that my border matches it so it works properly. So my background and my
border-color stay the same. And here on my highlight, which is this one here, I have sort of the default styling, but then I'm going back to those variables for when I hover on top. And you're gonna see those are all gonna sorta
switch around after. So what I've done is when we have that nav-scrolled
class that comes in, I don't have to go through
and find my hover here and find my highlight hover and
go and find the other thing. All I'm doing is switching
these things here, so I'm just switching
those three variables. And that means, when that
class does get put on here, let's go put it back on, all the colors throughout
all that are switching. So my hover color gets
switched over to black on that. It gets switched over
to black on this one. My background is switched. All of that is happening
just by changing this, so super, super handy, and a nice use for custom properties. I've just put a little
drop shadow on this, too, to make it stand out a little bit more. So the real magic of
this one is going to be getting it to switch when
we scroll up and down and it's not that hard to do. We just need to add or remove that class. But we don't want to do it
with a scroll event listener. Because that means the whole time we're scrolling up and down, we're just firing off things like crazy. Whereas we could just listen for one very specific situation to happen and have it switch in that. And that's what Intersection Observer is really, really good for. Now I'm gonna be going a little bit, I'm not gonna be spending a lot of time looking at exactly how
we're building this out, because I've looked at the basics of Intersection Observer
already in another video. If you've already watched that, you're ready to go. If you haven't watched it, it might be a good idea
to go check it out. If you want to try and
follow along with this one, you maybe able to be perfect and you'll be able to
follow along no problem, but if ever I gloss over something, and you're not sure what I
was doing or why I did that, go and check out the original video. The link for it is in
the description below. And with that, you'll
get a better idea of how and why I'm writing all of
these things and then just, 'cause in this one I'm just focusing on this specific situation and
not on the general happenings or the general behavior of
an Intersection Observer. So we're gonna start off by
creating a couple of things that we need to keep track of. So one of them is my header itself because we need to
change the class on that, so document.querySelector. And we wanna look at my header. And the second one that we
want to watch for, const, and I'm gonna call it sectionOne and that will be document.querySelector. And in this case, I
called it a home-intro. And the home-intro is this here, this dark background
that we're looking at . So what we wanna do is, we're gonna be listening like when is this leaving the screen? And when it leaves the screen, we want to change the background on that. And then when it comes
back into the screen, we want the background
to change again on it. So this is what we're gonna be watching and then this is what we're
gonna be changing the class on. So with those set up, let's come and create our observer itself. So we're gonna do const, now in the original tutorial
on this I just did observer, I'm gonna call this one sectionOneObserver because that's what we're looking at. And because once we get through all the different parts of this, we're going to have a bunch of
different observers going on for this one, so we can't
just call it observer, but it will still be a
new Intersection Observer. And let's go and make this bigger, just for now, and I'll shrink it back down after once we start getting some stuff. Because on our Intersection Observer, we need a few different things. One of them is going to be a function, so we can say function
like that, open and closed. And the second thing we are
gonna need is the options. So we have the two of those coming in. Now the options, I'm also
gonna change the name of it. Instead of just being options, let's say sectionOneOptions, just so we can keep track of it. And so we don't run into any errors, I'm gonna create that right away, sectionOneOptions is equal to, and I'm just gonna leave
it blank for the moment but we'll come through and
actually add some stuff in there a little bit after. So here in our function, we also need to come in
and watch for our entries. And I'm also gonna put
the observer in here, even though I'm not sure we're
gonna need it in this case, 'cause we're not gonna unobserve anything, but we'll throw it in
there as a precaution. All right, cool. So we have our new Intersection
Observer doing a function. It's going to be looking at
the entries and add itself. And then we're also going to
be bringing in these options that are up there. And right here we can
start our actual function. So I'm just gonna hit save on that. You can see it reposition
things a little bit. That's just prettier, that's organizing this to try and make it a little bit more readable. So here in my function, what we're gonna do is we
want my entries and forEach, if you watch the other video, you know what we're gonna do here, each entry now will use an arrow function. And we can say that, well let's start off
by doing a console log to make sure that this
is actually working, so entry.target, 'cause I always
like checking along the way instead of running into a problem after everything else that I've done. So we can do our sectionOneObserver
needs to observe, and we want it to observe sectionOne. So let's save that. So let's shrink this back down, 'cause I don't think we
need it so big anymore. And there we go, we can see that it fired off right when the page loaded in there. So perfect, it is actually working. So let's delete this console.log, 'cause we won't really be needing it since we know it is working. In this case, what do we want to do? So let's think about this for a second. When I scroll down, when this leaves the page, I want the nav class to come in. So let's look for one
thing at the beginning. So we're gonna say if entry, entry not entries, if entry is intersecting, and again, if you're not sure
why this is going to work, please do check out the
original video that I did where what the whole is intersecting thing and other stuff along the way. So if my entry is
intersecting with the page, we don't wanna have that nav class is scrolled on here right? So say we scroll down and it adds it, if we come back up, we wanna remove it. So if entry is, actually, let's start off with if the
entry isn't intersecting. So if it's not intersecting with the page, we wanna add that class on there, right? So we can say if it isn't intersecting, we can do our headerclassList.add and add nav-scrolled to it. So if we save that it should, when we go down far enough, add that, there we go. So look at that, the class just came on. And if I go back up, well it doesn't leave now though. So that's a bit of a problem. So let's refresh that again and
just watch it one more time. So when I scroll down, there we go, it clicks on and we see it. Okay, so that's cool. So now, we could write this straight in as just an else statement. So if it isn't intersecting,
we can do that, else, we could say that header.classList.remove nav-scrolled. Now this will mean it's going to try, so when it is intersecting,
like right now, it'd try and remove it. The class isn't there. I don't think that's an issue though, but if you wanted to, you could make this an
else-if statement and say, if it is intersecting and if the class list
contains nav-Scrolled, to remove it. But now it should work. Where we're gonna scroll down, it adds it, and then when it comes back
into the screen, it removes it. So we can see, just like that, it's going back and
forth and it is working. I do have a transition on the background so you can see it's like, it sorta transitions in and out. It's hard to see on the white, but it is transitioning in and out. But the one thing that's
a little bit annoying is we lose what we're looking at here, right? At one point, this is still
intersecting with the screen so it hasn't come in yet. So this is where we can use
our sectionOneOptions here. And I can set the rootMargin. So if I set the rootMargin, it works just like the regular one. And I wanna work off the top of the page. So it can be a percentage or pixel values. So we'll stick with pixels. So we'll say negative 200
from the top of the page and then we'll just do
zero for the rest of them. And you have to put zero
pixels, it can't just be zero. And so now, you can see it's, even though I can see this
it's actually white now, once I scroll to a certain point, so it's once this is within, and I put negative 200 'cause I'm pushing it
downwards by 200 pixels. So the way it's working now
is it's going down 200 pixels, so it's not when it
intersects the viewport, it's when it intersects 200 pixels away from the top of the viewport. So now, when I get to there, it's switching back and forth. So we're sort of preemptively switching it before we can't read the text, which just makes it a
little bit easier to read and you can see the transition a lot nicer when that switches back and forth now too. And of course, you can play
with that number and everything, but you can't use viewport units on that, you do have to use pixels or
percentages for the rootMargin. That was fun, wasn't it? I had a lot of fun doing that. I hope you had fun watching it and I hope you learned a few
things along the way as well. If you did, please let
me know in the comments. Or if you think of other ways you could be able to use this maybe, or other ways or approaches you could do, please leave a comment
down below and let me know. I'd love to have a bit
of a discussion about it. But if you really wanna
have an in-depth discussion, I'd encourage coming
over to the community. My community is a free Discord channel. You can just go down in
the description below, find the link, click on it, and you're in. There's literally no other steps. It's super, super easy to do. There's a whole bunch of people in there. We're having lots of fun
and cool discussions. And if you have questions,
or run into problems, it's a lot easier to ask
there and find out stuff there and just also meet people along the way than it is in the YouTube
comments down below. So I look forward to seeing
you there in the community, big thank you for watching all of this, a double-big super thank you to my patrons for helping support everything
I do here on my channel. Thank you once again for watching. Next week, we're gonna be
looking at another thing you can do with Intersection Observers. So please come and check that one out too. It's gonna be those slidey images. You know when you're scrolling down and things either fade
in or they just appear. So if you haven't yet subscribed, hit that Subscribe button so you see that video when it comes out, 'cause you don't want to miss that. It's gonna be pretty cool too. But until then, of course, don't forget to make your
corner of the internet just a little bit more awesome.