Hide navigation on scroll down and reveal on scroll up

About 2 years ago I asked the same question. PAULOB came up with the following example. Since that time i used this code a couple of times and it is working great. However, now I’m wondering if the same can be accomplished in a CSS (only) way (no js). Another wish is that this only takes effect on devices larger than 960px:

@media (min-width: 960px)

HTML:

<nav class="navbar">
	<a class="nav-link" href="">Home</a>
    <a class="nav-link" href="">About</a>
    <a class="nav-link" href="">Contact</a>
</nav>

Note: I prefer not to work with a height on the navbar!

Thank you in advance

No you can’t accomplish this without js as it depends on detecting if the user has scrolled and which way they have scrolled.

You would be better just having a position:sticky header which will stay in place all the time but allow a flexible height to avoid initial overlaps unlike position:fixed.

If you use position:sticky instead of fixed you can remove the need for the JS cloned element in that previous example.

e.g.

I’m sure one of the JS experts could greatly simplify the previous JS code I posted as I just amended it from somewhere else.

Hello Paul. Sorry for the late reaction. Unfortunately, due to circumstances, I was unable to respond any earlier. Your example works great but it would indeed be nice if the JS part was a bit shorter/simpel. So if there are JS experts who would / can help me with this, I would really appreciate it.

Thanks in advance

Moved to #javascript forum.

1 Like

Here’s a significant simplification.

$(document).ready(function domReady() {
    var $navigation = $(".navigation");
    var hasScrolled;
    var lastScrollTop = 0;

    function scrollDirection(st) {
        var direction = Math.sign(st - lastScrollTop);
        if (direction < 0) {
            return "up";
        }
        if (direction > 0) {
            return "down";
        }
    }
    function autoshowNav() {
        var st = $(window).scrollTop();
        if (scrollDirection(st) === "down") {
            $navigation.removeClass("show-nav");
        }
        if (scrollDirection(st) === "up") {
            $navigation.addClass("show-nav");
        }
        lastScrollTop = st;
    }

    $(window).scroll(function scrollWindowHandler() {
        hasScrolled = true;
    });

    setInterval(function scrollChecker() {
        if (hasScrolled) {
            autoshowNav();
            hasScrolled = false;
        }
    }, 250);
});

Does this simplification remove any needed features?

1 Like

Looks good to me Thanks Paul :slight_smile:

After further simplication, we have the following code:

$(document).ready(function domReady() {
    var $navigation = $(".navigation");
    var navClass = "show-nav";
    
    var lastScrollTop = 0;
    
    function scrollDirection(scrollTop) {
        var direction = Math.sign(scrollTop - lastScrollTop);
        return (direction < 0 ? "up" : "down");
    }
    function autoshowNav() {
        var scrollTop = $(window).scrollTop();
        var scrollDir = scrollDirection(scrollTop);
        lastScrollTop = scrollTop;

        $navigation.toggleClass(navClass, scrollDir === "up");
    }

    var hasScrolled = false;
    $(window).scroll(function scrollWindowHandler() {
        hasScrolled = true;
    });
    setInterval(function scrollChecker() {
        if (hasScrolled) {
            autoshowNav();
            hasScrolled = false;
        }
    }, 250);
});
1 Like

@Paul_Wilkins. That is for sure a significant simplification :ok_hand:. Thanks a lot!!!

@PaulOB Thanks a lot for your input Paul.

1 Like

I have one last question regarding the navbar showing. As it is now the navbar shows when the scrollbar is near the top. How do I make it so that the navbar shows up as soon as I start scrolling up again?

Thank you in advance

I don’t see that happening in any of the examples?

The navigation will appear whenever you start to scroll upwards no matter where you are in the document. There is a slight delay added to the css so that it doesn’t keep flicking on and off when someone can’t control the mouse precisely. You can remove the delay and speed up the transition but I feel it loses its usefulness in that way.

.show-nav {
  top: 0;
  transition: .2s ease-in-out;/* delay removed and transition sped up*/
  box-shadow: 0 0 10px 10px rgba(0, 0, 0, 0.4);
  opacity:1;
}

@PaulOB.

As usually you 're right. I just saw it on my desktop on any of my other devices it was all OK :+1:

Would it help to change it from 250 for every quarter second, to 100 for ten times a second instead?
I wouldn’t take it lower than that though.

    setInterval(function scrollChecker() {
        ...
    }, 100);
2 Likes