{"id":5703,"date":"2021-10-28T02:00:00","date_gmt":"2021-10-28T00:00:00","guid":{"rendered":"https:\/\/alvarotrigo.com\/epa\/sticky-navbar\/"},"modified":"2024-07-17T14:48:07","modified_gmt":"2024-07-17T12:48:07","slug":"sticky-navbar","status":"publish","type":"post","link":"https:\/\/alvarotrigo.com\/blog\/sticky-navbar\/","title":{"rendered":"How to Create a Sticky Navbar [CSS &#038; JS]"},"content":{"rendered":"\n<p>To create a sticky navbar, you use the <code>position: fixed;<\/code> CSS property to &#8220;stick&#8221; your navbar to the viewport and <code>position: sticky;<\/code> to make it stick to its parent element.<\/p>\n\n\n\n<p>In this post, you&#8217;ll learn what all of this means, and <strong>how to make a sticky navbar<\/strong> for your own site.<\/p>\n\n\n\n<p>Let&#8217;s go!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-is-a-sticky-navbar%3F\">What <em>Is<\/em> a Sticky Navbar?<\/h2>\n\n\n\n<p>But before we proceed, we need to clear one thing up. What exactly do you mean by &#8220;sticky&#8221;?<\/p>\n\n\n\n<p>You see, in the world of CSS, <code>sticky<\/code> means something very specific. In fact, there are two settings you use to &#8220;stick&#8221; an element to a specific part of the screen while the visitor scrolls. These are:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">position<\/span>: <span class=\"hljs-selector-tag\">sticky<\/span>;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Or&#8230;<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">position<\/span>: <span class=\"hljs-selector-tag\">fixed<\/span>;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>There&#8217;s a big difference between them:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>fixed<\/code> elements stay in the same position on the viewport, regardless of scrolling. So, as you scroll down the page, they seem to &#8216;float&#8217; over the content.<\/li>\n\n\n\n<li><code>sticky<\/code> elements are similar &#8211; they stay in the same position on the viewport, regardless of scrolling, <em>but only within their parent element<\/em>. When the viewport reaches the end of a sticky element&#8217;s parent, it will behave like a relatively positioned element.<\/li>\n<\/ul>\n\n\n\n<p><strong>In this post, you&#8217;ll learn how to make a commonly used version of the sticky navbar<\/strong> &#8211; one that starts out positioned in your site&#8217;s header but not right at the top. Then, <strong>as the visitor scrolls past, it &#8220;sticks&#8221; to the top of the screen<\/strong> and stays in view as they scroll.<\/p>\n\n\n\n<p>Here&#8217;s how you do it&#8230;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"1)-make-a-simple-website-for-the-sticky-navbar\">1) Make a Simple Website for the Sticky Navbar<\/h2>\n\n\n\n<p>First, let&#8217;s build a site where the sticky navbar can be installed. We&#8217;ll make a simple one-page site with some jokes from famous comedians.<\/p>\n\n\n\n<p>Each link in our sticky navbar will point to a different section of the site &#8211; so we&#8217;ll use a few <code>&lt;section><\/code> elements with some space for content inside. Here&#8217;s the structure:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>And here&#8217;s the CSS:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@import<\/span> url(<span class=\"hljs-string\">'https:\/\/fonts.googleapis.com\/css2?family=Caveat&amp;family=Poppins:wght@300&amp;display=swap'<\/span>);\n\n<span class=\"hljs-selector-tag\">body<\/span> {\n  <span class=\"hljs-attribute\">font-family<\/span>: poppins, sans-serif;  \n  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0px<\/span>;\n}\n\n<span class=\"hljs-selector-tag\">section<\/span> {\n  <span class=\"hljs-attribute\">min-height<\/span>: <span class=\"hljs-number\">100vh<\/span>;\n}\n\n<span class=\"hljs-selector-tag\">article<\/span> {\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">90%<\/span>;\n  <span class=\"hljs-attribute\">max-width<\/span>: <span class=\"hljs-number\">600px<\/span>;\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">20px<\/span>;\n  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0px<\/span> auto;\n}\n\n<span class=\"hljs-selector-tag\">h2<\/span> {\n  <span class=\"hljs-attribute\">text-align<\/span>: center;\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">40px<\/span> <span class=\"hljs-number\">0px<\/span> <span class=\"hljs-number\">0px<\/span> <span class=\"hljs-number\">0px<\/span>;\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">3em<\/span>;\n}\n\n<span class=\"hljs-selector-tag\">p<\/span> {\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">1.5em<\/span>;\n  <span class=\"hljs-attribute\">text-align<\/span>: center;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We can then style each individual section via it&#8217;s <code>id<\/code>, so the section for the comedian Bill Hicks could look like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">section<\/span><span class=\"hljs-selector-id\">#bill-hicks<\/span> {\n  <span class=\"hljs-attribute\">background<\/span>: <span class=\"hljs-built_in\">rgb<\/span>(<span class=\"hljs-number\">123<\/span>,<span class=\"hljs-number\">211<\/span>,<span class=\"hljs-number\">232<\/span>);\n  <span class=\"hljs-attribute\">background<\/span>: <span class=\"hljs-built_in\">linear-gradient<\/span>(<span class=\"hljs-number\">135deg<\/span>, rgba(<span class=\"hljs-number\">123<\/span>,<span class=\"hljs-number\">211<\/span>,<span class=\"hljs-number\">232<\/span>,<span class=\"hljs-number\">1<\/span>) <span class=\"hljs-number\">0%<\/span>, <span class=\"hljs-built_in\">rgba<\/span>(<span class=\"hljs-number\">232<\/span>,<span class=\"hljs-number\">123<\/span>,<span class=\"hljs-number\">165<\/span>,<span class=\"hljs-number\">1<\/span>) <span class=\"hljs-number\">0%<\/span>, <span class=\"hljs-built_in\">rgba<\/span>(<span class=\"hljs-number\">255<\/span>,<span class=\"hljs-number\">50<\/span>,<span class=\"hljs-number\">50<\/span>,<span class=\"hljs-number\">1<\/span>) <span class=\"hljs-number\">100%<\/span>);\n  <span class=\"hljs-attribute\">color<\/span>: <span class=\"hljs-number\">#40081a<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>And after Googling some jokes and adding some more styles for each section, we get this:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_qBXjaNe\" data-src=\"\/\/codepen.io\/anon\/embed\/qBXjaNe?height=450&amp;theme-id=1&amp;slug-hash=qBXjaNe&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed qBXjaNe\" title=\"CodePen Embed qBXjaNe\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"2)-build-the-navbar\">2) Build the Navbar<\/h2>\n\n\n\n<p>Now to add the navbar, which we&#8217;ll place below the <code>#header<\/code> section in the markup. <strong>First, the HTML<\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"header\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>Let's read some jokes!<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">nav<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#header\"<\/span>&gt;<\/span>Home<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#tim-vine\"<\/span>&gt;<\/span>Tim Vine<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#bill-hicks\"<\/span>&gt;<\/span>Bill Hicks<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#stewart-francis\"<\/span>&gt;<\/span>Stewart Francis<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">nav<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Then, some CSS<\/strong> to make it look more presentable and to position it at the top of the page:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">nav<\/span> {\n  <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-number\">#3a24f0<\/span>;\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">10px<\/span>;\n  <span class=\"hljs-attribute\">text-align<\/span>: center;\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n\n  <span class=\"hljs-comment\">\/* Pay special attention here! *\/<\/span>\n  <span class=\"hljs-attribute\">position<\/span>: sticky;\n  <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">0px<\/span>;\n}\n\n<span class=\"hljs-selector-tag\">nav<\/span> <span class=\"hljs-selector-tag\">a<\/span> {\n  <span class=\"hljs-attribute\">color<\/span>: white;\n  <span class=\"hljs-attribute\">text-decoration<\/span>: none;\n  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0px<\/span> <span class=\"hljs-number\">10px<\/span>;\n}\n\n<span class=\"hljs-selector-tag\">nav<\/span> <span class=\"hljs-selector-tag\">a<\/span><span class=\"hljs-selector-pseudo\">:hover<\/span> {\n  <span class=\"hljs-attribute\">text-decoration<\/span>: underline;\n}\n\n<span class=\"hljs-keyword\">@media<\/span>\n(<span class=\"hljs-attribute\">prefers-reduced-motion:<\/span> no-preference) {\n  <span class=\"hljs-selector-tag\">html<\/span> {\n    <span class=\"hljs-attribute\">scroll-behavior<\/span>: smooth;\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Which turns out like this:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_eYEZGea\" data-src=\"\/\/codepen.io\/anon\/embed\/eYEZGea?height=450&amp;theme-id=1&amp;slug-hash=eYEZGea&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed eYEZGea\" title=\"CodePen Embed eYEZGea\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"how-this-makes-the-navbar-sticky\">How This Makes the Navbar Sticky<\/h3>\n\n\n\n<p>So how does this work?<\/p>\n\n\n\n<p>Well, as you may remember, <code>fixed<\/code> sticks an element to the viewport and <code>sticky<\/code> sticks it to its parent element. But here, our navbar is below the header in the markup rather than being a child of it. So its parent is <code>body<\/code>!<\/p>\n\n\n\n<p>We gave the element a <code>top<\/code> value of 0. Until the element reaches that position in the viewport, it will behave as if it has <code>position: relative<\/code>. Once the top of the element reaches the top of the viewport, <code>position: sticky<\/code> kicks in, and it behaves as if it has <code>position: absolute<\/code>.<\/p>\n\n\n\n<p>This is a really cool solution and means you don&#8217;t have to use JS to create this effect. However, it only works when the navbar&#8217;s parent is <code>&lt;body&gt;<\/code>. If that&#8217;s not possible in your case, don&#8217;t worry! There&#8217;s another way&#8230;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"3)-creating-a-sticky-navbar-with-js---initial-positioning\">3) Creating a Sticky Navbar with JS &#8211; Initial Positioning<\/h2>\n\n\n\n<p>Let&#8217;s say, for whatever reason, your navbar has to be a child of your <code>#header<\/code>, but you still want to make it sticky.<\/p>\n\n\n\n<p>Your HTML may look something like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"header\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>Let's read some jokes!<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span> \n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">nav<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"main-nav\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#header\"<\/span>&gt;<\/span>Home<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#tim-vine\"<\/span>&gt;<\/span>Tim Vine<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#bill-hicks\"<\/span>&gt;<\/span>Bill Hicks<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#stewart-francis\"<\/span>&gt;<\/span>Stewart Francis<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">nav<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now <code>#main-nav<\/code>&#8216;s parent is <code>#header<\/code>, so if we use position sticky, it won&#8217;t stay in view after we&#8217;ve scrolled past it. For now, let&#8217;s just position it relatively:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-id\">#main-nav<\/span> {\n  <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-number\">#1e1e1e<\/span>;\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">10px<\/span>;\n  <span class=\"hljs-attribute\">text-align<\/span>: center;\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n  <span class=\"hljs-attribute\">position<\/span>: relative;\n  <span class=\"hljs-attribute\">box-sizing<\/span>: border-box;\n  <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">45px<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>At the moment, it&#8217;s just a standard navbar&#8230;<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_yLoXdJJ\" data-src=\"\/\/codepen.io\/anon\/embed\/yLoXdJJ?height=450&amp;theme-id=1&amp;slug-hash=yLoXdJJ&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed yLoXdJJ\" title=\"CodePen Embed yLoXdJJ\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"4)-creating-a-sticky-navbar-with-js---the-sticky-effect\">4) Creating a Sticky Navbar with JS &#8211; the Sticky Effect<\/h2>\n\n\n\n<p>Because the navbar&#8217;s parent isn&#8217;t <code>body<\/code>, we&#8217;ll actually have to use <code>position: fixed<\/code> to stick the navbar to the top of the screen.<\/p>\n\n\n\n<p>Let&#8217;s put this into a class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-id\">#main-nav<\/span><span class=\"hljs-selector-class\">.sticky<\/span> {\n  <span class=\"hljs-attribute\">position<\/span>: fixed;\n  <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">0<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, we need to add this class to the #main-nav element when the user scrolls past it.<\/p>\n\n\n\n<p>To know if the visitor has scrolled past the navbar, we need to check two things:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>How far the navbar is from the top of the screen<\/li>\n\n\n\n<li>How far the visitor has scrolled<\/li>\n<\/ol>\n\n\n\n<p>We can find out (1) with the following:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">let<\/span> navbar = <span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">\"main-nav\"<\/span>);\n<span class=\"hljs-keyword\">let<\/span> navPos = navbar.getBoundingClientRect().top;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>For (2), we first need to add an event listener to detect scrolling and then store the scroll position in a variable.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">window<\/span>.addEventListener(<span class=\"hljs-string\">\"scroll\"<\/span>, e =&gt; {\n  scrollPos = <span class=\"hljs-built_in\">window<\/span>.scrollY;\n});\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id=\"adding-the-sticky-class-to-the-navbar\">Adding the sticky class to the navbar<\/h3>\n\n\n\n<p>Great, we now have the information we need. When the user scrolls, we&#8217;ll check whether the new scroll position (<code>scrollPos<\/code>) is greater than the navbar&#8217;s position (<code>navPos<\/code>) and if so, add the class.<\/p>\n\n\n\n<p>But hold on a second!<\/p>\n\n\n\n<p>When we do this, we&#8217;re taking a relatively positioned element and making it absolute. This takes it &#8216;out of the flow&#8217; of the markup, and any elements below it will jump upwards to fill the empty space it left behind.<\/p>\n\n\n\n<p>To offset this, we will simply add 45px of padding to the first element after the header, which, in this case, is the <code>#tim-vine<\/code> element. Since the navbar is 45px high, this will prevent the content from &#8216;jumping&#8217; upwards:<\/p>\n\n\n\n<p>The new class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.navbarOffsetMargin<\/span> {\n  <span class=\"hljs-attribute\">padding-top<\/span>: <span class=\"hljs-number\">45px<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>&#8230;and the JS that makes it all work:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">let<\/span> timVine = <span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">\"tim-vine\"<\/span>);\n\n<span class=\"hljs-built_in\">window<\/span>.addEventListener(<span class=\"hljs-string\">\"scroll\"<\/span>, e =&gt; {\n  <span class=\"hljs-keyword\">let<\/span> viewportHeight = <span class=\"hljs-built_in\">window<\/span>.innerHeight;\n  <span class=\"hljs-keyword\">let<\/span> scrollPos = <span class=\"hljs-built_in\">window<\/span>.scrollY;\n  <span class=\"hljs-keyword\">if<\/span> (scrollPos &gt; navPos) {\n    navbar.classList.add(<span class=\"hljs-string\">'sticky'<\/span>);\n    header.classList.add(<span class=\"hljs-string\">'navbarOffsetMargin'<\/span>);\n  } <span class=\"hljs-keyword\">else<\/span> {\n    navbar.classList.remove(<span class=\"hljs-string\">'sticky'<\/span>);\n    header.classList.remove(<span class=\"hljs-string\">'navbarOffsetMargin'<\/span>);\n  }\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Give it a try below!<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_MWvoMjj\" data-src=\"\/\/codepen.io\/anon\/embed\/MWvoMjj?height=450&amp;theme-id=1&amp;slug-hash=MWvoMjj&amp;default-tab=js,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed MWvoMjj\" title=\"CodePen Embed MWvoMjj\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"5)-highlight-active-navbar-sections\">5) Highlight Active Navbar Sections<\/h2>\n\n\n\n<p>With navbars, it&#8217;s customary to highlight the section of the site that the visitor is currently on.<\/p>\n\n\n\n<p>The logic here is very similar to what we&#8217;ve just done with the navbar. First, we create a class to flip the colors of the navbar link when it&#8217;s active:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">nav<\/span> <span class=\"hljs-selector-tag\">a<\/span><span class=\"hljs-selector-class\">.active<\/span> {\n  <span class=\"hljs-attribute\">color<\/span>: <span class=\"hljs-number\">#1e1e1e<\/span>;\n  <span class=\"hljs-attribute\">background<\/span>: white;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I also added <code>5px<\/code> of padding to <code>nav a<\/code>, to give it a little breathing room, and added the <code>active<\/code> class to the first section &#8211; since the user will land on that section:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#header\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"active\"<\/span>&gt;<\/span>Home<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now, all we have to do is add and remove this class from the <code>a<\/code> elements within the navbar when the relevant section is in view.<\/p>\n\n\n\n<p>The new JS we need for this is shown below:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">let<\/span> navbarLinks = <span class=\"hljs-built_in\">document<\/span>.querySelectorAll(<span class=\"hljs-string\">\"nav a\"<\/span>);\n\n<span class=\"hljs-built_in\">window<\/span>.addEventListener(<span class=\"hljs-string\">\"scroll\"<\/span>, e =&gt; {\n\n scrollpos = <span class=\"hljs-built_in\">window<\/span>.scrollY;\n  <span class=\"hljs-keyword\">if<\/span> (scrollpos &gt; (viewportHeight - navHeight)) {\n    navbar.classList.add(<span class=\"hljs-string\">'sticky'<\/span>)\n  } <span class=\"hljs-keyword\">else<\/span> {\n    navbar.classList.remove(<span class=\"hljs-string\">'sticky'<\/span>)\n  }\n\n  navbarLinks.forEach(<span class=\"hljs-function\"><span class=\"hljs-params\">link<\/span> =&gt;<\/span> {\n    <span class=\"hljs-keyword\">let<\/span> section = <span class=\"hljs-built_in\">document<\/span>.querySelector(link.hash);\n    <span class=\"hljs-keyword\">if<\/span> (scrollPos + <span class=\"hljs-number\">150<\/span> &gt; section.offsetTop &amp;&amp; scrollPos + <span class=\"hljs-number\">150<\/span> &lt; section.offsetTop + section.offsetHeight ) {\n      link.classList.add(<span class=\"hljs-string\">\"active\"<\/span>);\n    } <span class=\"hljs-keyword\">else<\/span> {\n      link.classList.remove(<span class=\"hljs-string\">\"active\"<\/span>);\n    }\n  });\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Going through the new additions line-by-line:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"get-the-links-in-the-sticky-navbar\">Get the Links in the Sticky Navbar<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">let<\/span> navbarLinks = <span class=\"hljs-built_in\">document<\/span>.querySelectorAll(<span class=\"hljs-string\">\"nav a\"<\/span>);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This grabs all the <code>a<\/code> elements within the <code>nav<\/code> element and puts them into an array called <code>navbarLinks<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"loop-through-the-links-in-the-sticky-navbar\">Loop Through the Links in the Sticky Navbar<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">navbarLinks.forEach(<span class=\"hljs-function\"><span class=\"hljs-params\">link<\/span> =&gt;<\/span> {\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We&#8217;re gonna loop through each of our links and run the code inside this block. Within this block, we&#8217;ll use the alias &#8216;link&#8217; to refer to our links.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"get-the-section-element-that-the-nav-link-points-to\">Get the Section Element that the Nav Link Points to<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">let<\/span> section = <span class=\"hljs-built_in\">document<\/span>.querySelector(link.hash);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><code>link.hash<\/code> refers to the target URL of the link. This line scans the page for an element with that name, and if it finds one, stores it in the <code>section<\/code> variable.<\/p>\n\n\n\n<p>Since the links point to the sections within the page, this will return the section that the link is pointing to!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"check-if-the-section-is-currently-on-screen\">Check if the Section is Currently On-Screen<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">if<\/span> (scrollPos + <span class=\"hljs-number\">150<\/span> &gt; section.offsetTop &amp;&amp; scrollPos + <span class=\"hljs-number\">150<\/span> &lt; section.offsetTop + section.offsetHeight ) {\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This should be familiar to you &#8211; it&#8217;s similar to the logic we used previously. There are two differences, though:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\n<p>This time, we also check whether the bottom of the element (i.e., its offsetTop plus its height) is <em>greater<\/em> than the scroll position. If it is, that means the user has scrolled past it, so we can remove the <code>active<\/code> class.<\/p>\n<\/li>\n\n\n\n<li>\n<p>I&#8217;ve added an extra 150 pixels to <code>window.scrollY<\/code>. Why? Well, imagine you&#8217;ve scrolled 1 pixel above the top of a section.<\/p>\n<\/li>\n<\/ol>\n\n\n\n<p>In this case, your whole screen, apart from that 1 pixel, is taken up by that section. So even though the top of the viewport hasn&#8217;t officially reached that section, it really feels like that&#8217;s the one you&#8217;re &#8220;on&#8221;. Also, remember that 45px of the screen is taken up by the sticky navbar.<\/p>\n\n\n\n<p>Adding the 150px buffer helps adjust for this a bit.<\/p>\n\n\n\n<p>Of course, you don&#8217;t have to use 150px &#8211; use whatever feels right according to the screen size and the amount of content on the page.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"add-or-remove-the-active-class-on-the-navbar-links\">Add or Remove the Active Class on the Navbar Links<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">     link.classList.add(<span class=\"hljs-string\">\"active\"<\/span>);\n    } <span class=\"hljs-keyword\">else<\/span> {\n      link.classList.remove(<span class=\"hljs-string\">\"active\"<\/span>);\n    }\n  });\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If the above conditions are met, we&#8217;ll add the <code>active<\/code> tag to the link. If not, we remove it. Then we just close our brackets, and we&#8217;re all set!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-if-you-want-a-truly-fixed-navbar%3F\">What if You Want a Truly Fixed Navbar?<\/h2>\n\n\n\n<p>You might be wondering, what would you do if you wanted the navbar at the top of the screen all the time &#8211; without this sticky effect?<\/p>\n\n\n\n<p>It&#8217;s easy &#8211; just set up the <code>navbar<\/code> element with <code>position: fixed<\/code> and <code>top: 0<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-id\">#main-nav<\/span> {\n  <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-number\">#1e1e1e<\/span>;\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">10px<\/span>;\n  <span class=\"hljs-attribute\">text-align<\/span>: center;\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n  <span class=\"hljs-attribute\">position<\/span>: fixed;\n  <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">box-sizing<\/span>: border-box;\n  <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">45px<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then get rid of the JS that added the sticky class, as we don&#8217;t need that now. And hey presto!:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_xxLroEp\" data-src=\"\/\/codepen.io\/anon\/embed\/xxLroEp?height=450&amp;theme-id=1&amp;slug-hash=xxLroEp&amp;default-tab=js,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed xxLroEp\" title=\"CodePen Embed xxLroEp\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"6)-throttling-the-event-listener\">6) Throttling the Event Listener<\/h2>\n\n\n\n<p>Just one more step before we&#8217;re finished &#8211; if you&#8217;re using the JS approach, it&#8217;s a good idea to throttle the functions in the event listener.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-src=\"https:\/\/alvarotrigo.com\/blog\/assets\/imgs\/2021-10-28\/simpsons-meme.jpeg\" alt=\"Wrong Throttling Meme\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" class=\"lazyload\" \/><\/figure>\n\n\n\n<p>No, not that kind of throttling! Here&#8217;s what I mean&#8230;<\/p>\n\n\n\n<p>When the user scrolls, it might trigger 30, 50, or maybe even 100 events every second. Not a huge deal in our little project here, but in larger projects with more extensive functions, this could be an unnecessary performance hit.<\/p>\n\n\n\n<p>The solution is throttling. Basically, every time you call the function, you start a timer. If you try to call the function again before the timer runs out, the throttler won&#8217;t allow it.<\/p>\n\n\n\n<p>So, how do we set this up? Easy &#8211; use a library! <a href=\"https:\/\/lodash.com\/\" target=\"_blank\" rel=\"noopener nofollow\">Lodash<\/a> is a common one. Just download it and load it in your HTML file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"lodash.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Once that&#8217;s done, we just pull our code out of the event listener and into a function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">toggleClassesOnScroll<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  scrollpos = <span class=\"hljs-built_in\">window<\/span>.scrollY;\n  <span class=\"hljs-keyword\">if<\/span> (scrollpos &gt; (viewportHeight - navHeight)) {\n    navbar.classList.add(<span class=\"hljs-string\">'sticky'<\/span>)\n  } <span class=\"hljs-keyword\">else<\/span> {\n    navbar.classList.remove(<span class=\"hljs-string\">'sticky'<\/span>)\n  }\n  navbarLinks.forEach(<span class=\"hljs-function\"><span class=\"hljs-params\">link<\/span> =&gt;<\/span> {\n    <span class=\"hljs-keyword\">let<\/span> section = <span class=\"hljs-built_in\">document<\/span>.querySelector(link.hash);\n    <span class=\"hljs-keyword\">if<\/span> (section.offsetTop &lt;= <span class=\"hljs-built_in\">window<\/span>.scrollY + <span class=\"hljs-number\">300<\/span> &amp;&amp;\n        section.offsetTop + section.offsetHeight &gt; <span class=\"hljs-built_in\">window<\/span>.scrollY + <span class=\"hljs-number\">300<\/span>) {\n      link.classList.add(<span class=\"hljs-string\">\"active\"<\/span>);\n    } <span class=\"hljs-keyword\">else<\/span> {\n      link.classList.remove(<span class=\"hljs-string\">\"active\"<\/span>);\n    }\n  });\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now, we&#8217;d normally call that function from inside the event listener:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">window<\/span>.addEventListener(<span class=\"hljs-string\">\"scroll\"<\/span>, e =&gt; {\n  toggleClassesOnScroll() \n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>However, with <a href=\"https:\/\/lodash.com\/\" rel=\"nofollow noopener\" target=\"_blank\">Lodash<\/a>, we just put that function into the throttler like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">window<\/span>.addEventListener(<span class=\"hljs-string\">\"scroll\"<\/span>, e =&gt; {\n   _.throttle(toggleClassesOnScroll(), <span class=\"hljs-number\">100<\/span>);\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The 100 here just means 100 milliseconds. When our function is called, a 100-millisecond timer starts, and the function won&#8217;t run again until that timer runs out.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"final-result\">Final Result<\/h2>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_PoKjrGv\" data-src=\"\/\/codepen.io\/anon\/embed\/PoKjrGv?height=450&amp;theme-id=1&amp;slug-hash=PoKjrGv&amp;default-tab=js,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed PoKjrGv\" title=\"CodePen Embed PoKjrGv\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>Pretty cool eh? By loading the Lodash library, you open up a whole world of performance and tuning functions you can use, to save you having to write all that code by yourself.<\/p>\n\n\n\n<p>Another fantastic library you might want to check out is <a href=\"https:\/\/alvarotrigo.com\/fullPage\/\">fullPage.js<\/a>. This will really take your one-page site to the next level. With fullPage, the different sections of your site are locked at the size of the viewport, and when the user scrolls, they scroll down to the next section (and there are some fancy animations to get them there, as well as smooth scrolling).<\/p>\n\n\n\n<p>\n  <a href=\"https:\/\/alvarotrigo.com\/fullPage\/\">\n      <video width=\"680\" height=\"382\" controls muted autoplay loop playsinline>\n      <source src= \"https:\/\/cdn.jsdelivr.net\/gh\/alvarotrigo\/blog-assets\/videos\/fullPage_intro.mp4\" type=\"video\/mp4\" \/>\n      <source src= \"https:\/\/cdn.jsdelivr.net\/gh\/alvarotrigo\/blog-assets\/videos\/fullPage_intro.webm\" type=\"video\/webm\"\/>\n      Your browser does not support the video tag.\n      <\/source><\/source><\/video>\n  <\/a>\n<\/p>\n\n\n\n<p>This makes everything we&#8217;ve been talking about here much easier &#8211; it&#8217;s easy to check which navbar link is active because one page is active at a time. No need to mess around calculating offsets. So, have a look at <a href=\"https:\/\/alvarotrigo.com\/fullPage\/\">fullPage.js<\/a> and see what you think!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"related-articles\">Related articles<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/7-scroll-text-animations-css-and-js\/\">Stunning scroll text animations &#8211; CSS and JS<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/best-css-button-hover-effects\/\">Best CSS button hover effects<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/10-cool-css-animations-to-add-to-your-website\/\">10 cool CSS animations to add to your site<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/javascript-slider-how-to-make-one\/\">How to make a JavaScript slider<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/create-a-slider-with-pure-CSS\/\">Create a slider with CSS only<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>How to make a navbar stick to the window on scroll. What is the difference between fixed and sticky? Find out here!<\/p>\n","protected":false},"author":6,"featured_media":5702,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[105],"tags":[9,10],"class_list":["post-5703","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-developing","tag-css","tag-javascript"],"acf":[],"_links":{"self":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/5703","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/comments?post=5703"}],"version-history":[{"count":4,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/5703\/revisions"}],"predecessor-version":[{"id":14948,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/5703\/revisions\/14948"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/media\/5702"}],"wp:attachment":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/media?parent=5703"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/categories?post=5703"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/tags?post=5703"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}