Introduction and Demonstration of Sticky Navigation
Hello everyone. In this lesson, we are going to learn how to create a sticky navigation. So, let's take a look at the finished product. We can see that there's a navigation bar. And if we scroll just a bit, it scrolls with the page as you would expect. It's positioned in a standard fashion. But if we scroll to the point that it would normally scroll out of view, we can see that it locks or sticks to the top of the screen. And if we scroll back to the very top of the page, we can see that it reverts back to sort of standard positioning once again. So, this is a very useful feature in certain page layouts that are very long and you want to make sure that even when the users get towards the bottom of your page, they still have quick access to your vital links.
So, now that we've explained what a sticky navigation is and why it might be useful, it's time to learn how to code it. So, if we hop over to this other tab, this is a page where I've removed all of the code that makes the sticky behavior possible. So, we can see that if we scroll, this is just a completely standard page. So, we're going to rewrite the code together in order to make this navigation sticky once again. If you think of the sticky behavior as a recipe, here are the ingredients we're going to use. Number one, JavaScript for event handling. So, once we scroll to a certain point, then we want to run some code. Number two, we're going to use CSS for adjusting the positioning to activate fixed positioning. And number three, we're going to use another bit of JavaScript for adding and removing that fixed positioning at just the right moments. So let's dive right in. For a quick review of our existing code, you can see that we have a nav element with an unordered list for the links. We have a bit of CSS that gives everything background colors, colors, and size and position. And we have an empty JavaScript file. And you can see that we're using jQuery. So any code that we place between this bracket and this bracket will fire on the initial page load.
Now, before we start writing our JavaScript, let's use plain English to outline the logic that our code should use. We need to keep track of where the navigation sits when it's using its standard positioning. We also need to keep track of how far down the page we've scrolled, and we're going to need to update that value every time we scroll again. And finally, we'll use conditional logic to compare our two key values. So we'll say if the current scroll position is greater than or equal to the offset of the navigation bar then set it to fixed positioning and if the scroll position is less than this navigation bar then once again set it to use standard positioning. So the overall skeleton logic is pretty simple. Uh let's dive into writing the actual code to make it possible.
So, let's begin by creating a variable that keeps track of where the bar sits when it's using standard positioning. And more specifically, what we're really interested in is the top offset. So, how far in pixels from the top of the page does this navigation bar sit. So, var, we'll create a new variable. And we can name it anything we want. Uh, let's name it nav offset. And equals we'll select the element. So in our HTML we can see that it's just a nav element. So we want to select that and then we want to run the jQuery method named offset. So this really neat method will return an object telling you how far from the left and how far from the top an element is. And we're only interested in the top value. So then we'll say top. Now let's just make sure that everything's working. So we can alert that value in a message box. So we'll say alert nav offset. And if we refresh, we see that it's returning a value of 182, which looks about right to me. So, we now know how far down the bar sits. And the next thing we need to know is how far down from the top we've currently scrolled. So, we'll create a new variable. We can name it anything we want. I will choose scroll position. And we'll select the entire browser window and we'll use the jQuery method named scrollTop. Now, this will return how far down we've currently scrolled from the top of the page, but it will only run once when the page is first loaded. And if you think about our logic that enables the sticky navigation, we need to know that value of how far down we've scrolled every time we scroll. So, it needs to be constantly updating. So we'll wrap this code inside another jQuery method that will fire again and again and again every time we scroll. So we will write jQuery and select the entire browser window and then run the jQuery scroll method. Okay. We will then move this line where we're creating that variable into this scroll function so that every time we scroll this line will fire again and again. Now let's output this value somewhere in the browser just so you can see that it's updating correctly as we scroll. So in our HTML, let's add a temporary dummy div with a class of status. And then in our JavaScript, let's output this value into that div sort of as a proof of concept. So we'll select that status element and we'll update its text with this variable value. So now if we refresh and scroll you can see that right here in the top left as we scroll this value is constantly updating. Uh so we know that our code is working and we now have a variable which updates on the fly.
Toggle Fixed Class and Basic Fixed CSS
So now we can write our conditional code which compares the two values to see if we've scrolled down far enough to enable fixed position or not. So our code will look something like this. If scroll position is larger than or equal to the nav's offset, then run some code. Otherwise, else run a bit of different code. So now we can let CSS do the heavy lifting. We just want to use jQuery to add or remove a class at the right moment to enable fixed position. So if the condition is met, we'll select the nav element and add a class of fixed. And if the condition is not met then again we want to select the element and remove the class of fixed. So now we can hop over to our CSS file and create a new class named fixed and we'll simply say position fixed top zero. So now if we refresh our page we see that if we scroll nothing happens. Nothing happens. But once we get to that threshold, our link is now sticky or locked to the top. But our code isn't perfect yet. I'm sure you notice the awkward jumpy behavior. So when we get very close to the threshold, you can see that the content starts jumping around if we scroll very slowly. And even if we scroll quite rapidly, you can see that there's a jump in the content.
Fixing Layout Jumps with a Placeholder Wrapper
So what's happening here is that the CSS declaration of position fixed actually removes the element from the natural flow of the page. So once this element is set to position fixed, it's as if all of the content below it, so this content header and the paragraphs, they are no longer aware of this element on the page. So they're trying to move up to fill that empty space. Now, there are many different ways of solving this issue, but I'll show you one of my favorite strategies. It essentially consists of wrapping our menu bar in another element and then using jQuery to dynamically give that element the same height as the navigation bar. So that that way once our navigation bar becomes fixed position, there's still the wrapper element taking up the same amount of vertical space so that there's no jumping content whatsoever. So let's take a look at the code to make that possible. So we will hop over to our JavaScript file and write a few new lines of code. The first step is to select the nav element itself and wrap it with the jQuery wrap method with a new div. So we'll say div class nav placeholder. And the second step is to select this newly created div and give it the exact same height of the nav element itself. So we use the height method and we get to define what height we want. So we'll just select the height of the nav element. Oops. Okay. And the one final step is that we want to take this margin, the bottom margin of the nav, and let's just give this instead to the new wrapper element. So we'll say nav placeholder. Let's give that element the bottom margin. So now if we refresh our page, we see that once we scroll to the threshold, there's no awkward jumping content whatsoever.
Handling Fixed Width and Responsive Margins with Inner Wrappers
So now the only thing that remains is a bit of extra CSS because you can see that once we scroll to the threshold and the navigation becomes locked or sticky, you can see that the bar is no longer taking up the full width of our page like it does when it's using standard positioning. Now we mentioned earlier that fixed position elements are taken out of the natural flow of the page. So even though this is a block level element, once it's using fixed position, it sort of shrink wraps on itself and doesn't use the full 100% width that block level elements usually use. So we need to write a bit of new CSS to make this happen at all times. So we can begin by simply editing our CSS and the fixed class to contain a declaration of width 100%. So now if we refresh and we scroll to the point that it's locked, you can see that it takes up the full width, but it doesn't have any sort of margin on the right. I'm actually going to make our browser window a lot larger so you can see exactly what's going on. So you can see that we said width 100% and it is taking that command quite literally. This is because fixed position elements are taken out of the flow of the page and they're no longer aware of the size of their direct containing element. So, I'll show you how I like to handle this in JavaScript. I actually add an interior wrapping div to the nav element. So, we'll select nav and we'll use the jQuery method named wrap inner and we'll say div class nav inner. Okay. And then in CSS, what I'm going to do is select that newly created element of nav inner and I'm going to give it a max width of 700 pixels. And then I'll center it with margin auto. And then in the fixed position class, let's go ahead and give this a value of left zero. So now if we refresh we see that once the element is fixed position it's positioned correctly but the background is taking up the entire width. So now all we need to do is adjust our CSS for once the fixed class is added and we'll say background color transparent and we'll give that light blue color to this new nav inner class. So now if we refresh, we scroll down, we see that it keeps its exact same width and appearance and there's no jump in content. One of the final things to consider would be what if the browser window was smaller than that max width 700 pixels that we set. So for example, now if we refresh, we cross the threshold, we see that the sticky navigation is not observing any type of margins. And let's imagine that we wanted it to have the same universal 20 pixel margins on the side. So again, this is going to differ from layout to layout, but I want to give you a general idea of how I would handle this situation. So in script file, I would simply add another interior wrapping div. So I would select nav inner and then I would add a new div with a class of nav innermost. And then in the CSS, I would essentially move these properties to the innermost div. And then this middle div the nav inner we can give that horizontal 20 pixels padding. So now if we refresh and we cross the threshold we see that we still have the universal margins on the side and it works for all sorts of different screen sizes and we now have a silky smooth sticky navigation.
Recap and Closing
So that's going to wrap up this lesson. Let's review. We learned that the actual JavaScript logic, the skeleton logic is very simple. We just use a bit of variables and conditional logic and then we attach that to the scroll function so it fires and updates every scroll. And then we just use a bit of CSS to sort of wrangle the fixed position to do exactly what we want it to do. So again, that's going to conclude the lesson. Thank you very much for watching. Hope you feel like you learned something and stay tuned for more web development tutorials. Thanks. Bye.