 have a navigation that sticks to the top of the page as the person scrolls, but once the person starts scrolling, you'd like the navigation to change color, like you can see right here, or maybe you don't want to change the color, but you want to add a shadow or something like you can see right here. Well, sadly, we don't have like a stuck pseudo class or something like that that we can use in CSS. But luckily, we do have intersection observers in JavaScript, and they make this actually pretty easy to do. So to get started with this, the first thing that we need to have is a navigation. So I've set one up here, all in my primary header. And this is what I'm going to be focusing on. If you have a different setup, just follow whatever works for how you want to be doing things. For me, this header is going to just be going all the way across as we're going to see in a second. So that's why I want to be styling that. Now jumping over to the CSS, I have done some basic styling here. But the important part here is this position sticky that I've set up just so it keeps it on the top of the screen. So if we go and take a look at what I have right now, you can see that we have the navigation bar all the way across, which is in that primary header. And if I scroll down, it sticks to the top. And right now, it's really awkward because the color of it is matching the background color, which looks fine here. But then when it covers content, it looks really bad. And of course, if I didn't have a background on there at all, it would be even worse because then it's a little bit transparent. And it just makes things really hard. So we definitely want it to change when we scroll down. And you will notice here that I have put some custom properties. These custom properties will make life a lot easier when you're making changes. They're not necessary. But all I've done is I have my BG color here. The logo color is down on the logo class and the link color is on there. So if those are things that you'd want to be able to change, it's much easier because you only need one selector later on when you actually are making changes to it. But again, it's not necessary. It's how you want to work. What we're going to be focusing on here is the JavaScript to get all of this working. And as you can see, we're starting with nothing. So the first thing I'm going to do is let's make this a bit bigger because we are going to be writing some JavaScript. And we need to get two things. The first thing we need to get is the navigation itself. So we're just going to come in right away with a primary header here as a variable, just using my query selector and grabbing my primary header, nothing too fancy with that. And then there's different ways that we could actually do this. We could actually look for something like the H one here or like the next element in it and look for when that's passing by an intersection observer would work for that. The only problem is if you have different setups for different pages, it could be a little bit harder to have consistency there. And so if we do everything on the JavaScript side, since we're already having to use JavaScript for this anyway, it just makes it a little bit easier to be consistent. And I actually got this idea from a blog post by Ryan Mulligan, which I will link to in the description, but I really liked it for this type of thing. So what we're going to do is create a another variable here. And I'm going to call mine scroll watcher. That's pretty much its entire job is to watch for when we're scrolling. It could be like navigation intersect or whatever you want, just give it a name that to you make sense, because naming things is hard. And here instead of selecting something that's actually on the page, what we're going to do is do a document dot create element. And we're going to create a div. So the reason we're going to do this again, is just to make life a little bit easier, we don't want to have to come in and like remember to insert something on every page in the HTML or something like it's annoying doing that. So this will insert it into our document for us. Now just to make life a little bit easier for when we see it in the DOM to know what it's actually there for. And if ever you need to select it or do different things with it, what we're going to do is add an attribute. And so we can say is our scroll watcher, we can do a set attribute. And I'm going to do a data attribute of scroll watcher. And when you set an attribute, you do have to provide it what you're setting it to in this case, I don't need anything, I just want to have that data attribute on there. And the last thing we want to do is actually insert this actually into the page, we've created it within JavaScript, but we want to insert it somewhere. So we already have our primary header selected there. So we can take our primary header, and then we need to say before, and then we can say scroll watcher. So now if we jump back into our HTML, and we go and take a look in here in our dev tools, we should be able to see that we have our primary header, and then we have this data scroll watcher right here. So again, if you open up and you're seeing this, and you're wondering if you just had an empty div here, you'd be very, you would have no idea what this is. So it is handy having something on there that just gives us a little bit of context to what it's actually doing. And by having that on there, the idea is we can judge when that goes off screen or on screen, and then we can change the styles of other things because of that. So to be able to do this, we're going to create our intersection observer. And so I'm going to say const nav observer, and you can call it whatever you want here is going to be equal to a new intersection observer. And there we go. That's what we're going to be playing with. Now, when we use the intersection observer constructor, we need to pass it a callback function. And optionally, we have options that we can also use, which we'll take a look at in a little bit. But to start with, we'll just add in a callback function here, we could create a like a function and actually bring it in. But it's really small, we're going to be writing here. So I'm just going to include it right here. And so it's just like an anonymous function right there using an arrow function. And so let's start, we're going to keep things simple to begin with. We'll have to make a few little changes here, but we can say primary attribute class list, and we can toggle that. And I'm going to toggle a class called sticking because whether it's sticking or not sticking. So now this exists, but it's not actually being used yet. So we do need to call this. So we can say nav observer. And then we just tell it observe. And we have to tell it what we want it to be observing. So we want it to watch our or be paying attention to our scroll watcher. So with that in place, if I come and take a look here, we do our inspect, we have my primary header, and you can see it's already sticking. And this is an issue that we'll fix in a second. But it is there. And if I scroll down, it will turn off. And if I go up, it goes back on. So it's sort of backwards at the moment. But at least it's working. And we can see that it's doing something. So that is a start at least. So as a way to understand what's actually happening here, and I'm not deep diving the intersection observer here in depth, because I have covered it really in depth before, I'll link to that video in the description. But here what I'm going to write is entries. And this is, well, let's just put that there. And then here, we're going to do a console log console log of our entries to see what they actually are. And basically when our intersection observer is going, it can be watching a lot of different things, even though in this case, we're only going to ask it to watch one. But it returns an array of the different things and gives us information on those. So if we jump on over to our console, we can see here, we have the array coming in intersection observer entry. And if I take a look in there, we have only one of them. So there, and I can get information on it. So is visible is intersecting, and a lot of other things that are on there. And having this is intersecting as true or false. So if I scroll off, you can see that it should be here again, there we go, we can get that information. And now it is switched over to false. And then as we go up and down, it goes to true and false every time. So what we want to do is we want to know, is that one actually intersecting or not? So we don't need this here anymore. And this is another thing that I got from Ryan Mulligan. So I would encourage you to check out that blog post that I mentioned. But instead of doing like an if else statement, which you could definitely do here. But we can actually do this toggle in a bit of an interesting way. Because when we use this toggle method here, we can actually provide it a second parameter. And the second parameter here is when we saw that let's just bring this back on for a second, we do need to get like we have our intersection observer entry, we want to get this zero one here right here. So we, you know, we need the array itself. So there's other ways we can get it. But I'm just going to say that my entries and say zero. So we're just getting the information from that first one. And the main just do is intersecting. This is really cool. And basically that means the toggle is going to work actually, it's going to work exactly the same as what it's doing now. But if we want to switch how it's working, we can actually just say is not. So basically we're saying if it's not intersecting, right? And what this second parameter is doing is it's changes a little bit how the toggle works. So if this is false, if this is returning false, then the toggle can only remove a class. And if this is returning true, then the toggle can only add a class. And so is it not intersecting? As long as that is false, then we're only removing the class. And then if it is true, then we're only adding the class. So that's going to just sort of basically turn the behavior that we currently have on its head. So if we go back to our dev tools right here, we can see that now that primary header when the page loads is not getting that sticking class. And when we go like that, we scroll down, it's sticking. And now it's no longer sticking. So we've inverted the behavior that we just had before. So with that done, now what we can actually do is come back over to our CSS, and I can take my primary header and we're going to say sticking and we can change things. And this is where it's really nice to have custom properties that are locally scoped. And that's also why I put these underscores here, just to sort of indicate these are private properties, they're scoped here, that's just an optional way of naming things. But then I could change my background color here and let's just make that lighter. Let's just change my logo color because why not, we'll make it we'll add some we'll make it red. And then the link colors here can also let's make those also turn more to a red color just so we can see that things are going to change. So I can hit save on that, we can shrink this down. And when I scroll now, we can see that it switches over. So right away, I think that's like a nice little improvement or not really an improvement, it's still pretty ugly. But at least it's working. And then of course, you can come through and set like transition background color and 500 milliseconds or whatever you need. And for now, I'm just going to take these two off and we're just going to play with that background color. And so when I scroll down, you can see that it's working and then turning off. So and it transitions that as I scroll and then it goes back when we get to the top of the page. Now you might not want it to happen from the very top, you might want to wait until you've scrolled a little bit before that comes into effect. So we could do that either with CSS, selecting our scroll watcher. And that's why it's kind of nice to have this attribute on there, because then we could select it with our CSS. Or alternatively, we could pass the option to our intersection observer. And I'm going to do it that way. And again, these this option could be separated. And then you could bring it in. But I'm just going to put a comma here, and then another set of curly braces. And in there, I'm going to write root margin. And root margin, it's going to be a string. So you need your parentheses there. And you can either do it as percentages or pixels, but just make sure that you include pixels. I'm going to say 200 px, but of zero zero. And even though these are zero, they need to have a unit on them or it will not work and return an error. And this works just like margin. So I'm saying 200 pixels from the top, and then zero on the left, the right, and the bottom here. So now if I save that and I come, it's going to wait until I've scrolled 200 pixels down. And then you can see that the logo or the background changes. And then when I get back up, it changes back the other way. So it's always going to be in that threshold of 200 pixels, because that's what I've said it to here, rather than being at the top of the page. And of course, I'm coming through here, and I'm setting this just on like some basic styling on this, we could be doing this with all other things like we saw at the beginning with your different shadows and other stuff going on. Though I would recommend if you're going to do it with a shadow that's coming underneath, rather than doing or animating the shadow with the transition that comes in and out is actually to use a pseudo element instead, because it's better for performance. And if you'd like to know more about how to set that up and why it's better for performance, I have a video that covers that right here. And if you'd like to know more about intersection observers and deep diver into them, that video is also right here. And with that, I would like to thank my enablers of awesome and Rico, Michael, Simon, Tim and Johnny, as well as all my other patrons for their monthly support. And of course, until next time, don't forget to make your corner the internet just a little bit more awesome.