Skip to content
Advertisement

How can i show/hide navbar based on scroll position?

I am looking for a solution to apply a scroll based animation to my navbar. When i scroll down or up, i want to hide/show the navbar with a scroll animation. After some research i always find only solutions like the following.

var lastScrollTop; // This Varibale will store the top position

navbar = document.getElementById('navbar'); // Get The NavBar

window.addEventListener('scroll',function(){
 //on every scroll this funtion will be called
  
  var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
  //This line will get the location on scroll
  
  if(scrollTop > lastScrollTop){ //if it will be greater than the previous
    navbar.style.top='-80px';
    //set the value to the negetive of height of navbar 
  }
  
  else{
    navbar.style.top='0';
  }
  
  lastScrollTop = scrollTop; //New Position Stored
});
body{
  margin:0;
  padding:0;
}
.container{
  background:url('https://images.unsplash.com/photo-1497250681960-ef046c08a56e') no-repeat center center;
  height:170vh;
}
#navbar{
  position:fixed;
  top:0;
  left:0;
  width:100%;
  background:blue;
  border-radius:0 0 30px 30px;
  color:white;
  text-align:center;
  
  /*Define a height for NavBar*/
  height:80px;
  transition: 0.5s;
  /*and a transition time for a smooth appearence*/
  
}

footer{
  text-align:center;
  position:relative;
  bottom:0;
  left:0;
}
<div class="container">
  <navbar id="navbar">
    <h1>NAVBAR<h1>
  </navbar>
</div>
<footer>
  <h3>End of the Page</h3>
</footer>

If you scroll down or up, a css class or a style definition is applied to the navbar. But i want to show/hide the navbar, based on how much you scrolled. Say you open the page, the navbar is visible top: 0px, so you need to scroll maybe 80px down and every pixel you scrolled down, the navbar will be hidden pixel by pixel – so we get a nice scroll animation, instead of apply a property. The same happens when we scroll back up, only in reverse of course.

The idea comes from medium.com. If you open a post in mobile view, you can see a footer overlay which will be hide/show based on how much you scrolled:

enter image description here

How can i create the same kind of animation? Any ideas?

Advertisement

Answer

You have to change the value of scroll top.

…
// (1)
if (lastScrollTop == undefined) {
    lastScrollTop = scrollTop;
}

// (2)
if(scrollTop - lastScrollTop >= 80) { // if you've scrolled down 80px
    navbar.style.top='-80px';
    //set the value to the negetive of height of navbar 

    // (3)
    lastScrollTop = scrollTop; // New Position Stored

// (4)
} else if (lastScrollTop - scrollTop >= 80) { // if you've scrolled up 80px
    navbar.style.top='0';
    
    // (5)
    lastScrollTop = scrollTop; // New Position Stored
}
…
  1. Since the lastScrollTop isn’t being changed on every scroll, it needs to be set initially (when it has no value)

  2. For example: If scrollTop is, 81, and lastScrollTop is 1, then scrollTop - lastScrollTop will be 80 (and the condition is true). That will work after you have scrolled down 80 px

  3. Now that 80px has been reached, reset the property.

  4. Similar logic to (2), just reversed.

  5. Same as (3)

I hope this helps!

P.S. You can change the value, 80, to any number you want.

Edit:

This gets the distance between the last scroll and the current position, and changes the nav bar style based on that.

const navbar = document.getElementById("navbar");

            let lastScrollTop = 0;
            addEventListener("scroll", () => {
                // Current scroll position
                const scrollTop =
                    window.pageYOffset || document.documentElement.scrollTop;

                // check scroll direction
                const distance = scrollTop - lastScrollTop;
                const currentTop = parseInt(
                    getComputedStyle(navbar).top.split("px")
                );

                // Clamp value between -80 and 0
                let amount = Math.max(
                    Math.min(
                        currentTop +
                            (distance < 0
                                ? Math.abs(distance) // scrolling up
                                : -Math.abs(distance)// scrolling down
                                ) * 40, // (1)
                        0
                    ),
                    -80
                );

                console.log(amount, currentTop, Math.abs(distance));

                navbar.style.top = `${amount}px`;

                lastScrollTop = scrollTop;
            });
body {
                margin: 0;
                padding: 0;
            }
            .container {
                background: url("https://images.unsplash.com/photo-1497250681960-ef046c08a56e")
                    no-repeat center center;
                height: 170vh;
            }
            #navbar {
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                background: blue;
                border-radius: 0 0 30px 30px;
                color: white;
                text-align: center;

                /*Define a height for NavBar*/
                height: 80px;
                transition: 0.5s;
                /*and a transition time for a smooth appearence*/
            }

            footer {
                text-align: center;
                position: relative;
                bottom: 0;
                left: 0;
            }
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div class="container">
            <navbar id="navbar">
                <h1>NAVBAR</h1>
            </navbar>
        </div>
        <footer>
            <h3>End of the Page</h3>
        </footer>
    </body>
</html>
  1. This value can be changed to suit your needs — for reasons I couldn’t figure out, I needed to add this in order to make it scroll fast enough.

I hope this can point you in the right direction!

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement