Search code examples
javascriptjquerynavbarfixedsticky

How do I create a sticky nav bar?


I am trying to make my nav bar stick to the top of the page as I scroll down the page. I have included a JS fiddle: https://jsfiddle.net/1qsy0Lwu/ I followed a w3schools example exactly, and it's not working. Please help.

In my research I have noticed a difference between offsetTop and offset().top. i have a feeling the problem has to do with something in my css.

I also noticed that the links in the navbar don't work when offsetTop is applied in the javascript. Although no errors show in the console. However, when I implement offset().top, an error shows in the console...but the nav bar links work

HTML

<div id="navbar">
    <a class="active" href="#">Apps</a> 
    <a href="#">TAB 1 </a> 
    <a href="#">TAB 2</a>
    <a href="#">TAB 3</a>
    <a href="#">TAB 4</a>
</div>

<div class="container">
CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT  CONTENT 
</div>

CSS

#navbar {
overflow: hidden;
background-color: #161717;
margin-top: 0.1%;
text-align: center;
}

#navbar a {
display: inline-block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
 }

#navbar a:hover {
background-color: #ddd;
color: black;
 }

#navbar a.active {
background-color: #1e272d;
color: white;
 }

.container {
padding: 16px;
}

.sticky {
position: fixed;
top: 0;
width: 100%;
}

.sticky + .container {
padding-top: 1000px;
}

JS

$(document).ready(function () {

window.onscroll = function () { myFunction() };

var navbar = document.getElementById("navbar");
var sticky = navbar.offsetTop;

function myFunction() {
 if (window.pageYOffset >= sticky) {
    navbar.classList.add("sticky")
 } else {
    navbar.classList.remove("sticky");
 }
}

});

Solution

  • You could use pure css with position: sticky. To define how far from the top the value becomes sticky, modify the top property.

    nav {
      position: sticky;
      top: 0;
    }
    

    Example 1

    body {
      padding: 0;
      margin: 0;
    }
    
    nav {
      position: sticky;
      top: 0;
    }
    
    nav>ul {
      margin: 0;
      list-style-type: none;
      padding: 0;
      display: flex;
      flex-direction: row;
      background: red
    }
    
    nav>ul>li {
      padding: 10px;
    }
    <nav>
      <ul>
        <li>Item</li>
        <li>Item</li>
        <li>Item</li>
      </ul>
    </nav>
    <div>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
    </div>

    Example 2

    body {
      padding: 0;
      margin: 0;
    }
    
    nav {
      margin-top: 80vh;
      position: sticky;
      top: 0;
    }
    
    nav>ul {
      margin: 0;
      list-style-type: none;
      padding: 0;
      display: flex;
      flex-direction: row;
      background: red
    }
    
    nav>ul>li {
      padding: 10px;
    }
    <nav>
      <ul>
        <li>Item</li>
        <li>Item</li>
        <li>Item</li>
      </ul>
    </nav>
    <div>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
    </div>