Search code examples
javascripthtmlcssnavbarnav

How can I create a nav bar that is responsive relative to your location on the page?


I created this nav bar recently, it's the first nav bar I've made and I'm quite happy with it, that being said it didn't fully meet my vision:

First Nav

What I am trying to create is a nav bar that will respond relative to where you are on the page. For example if I'm at the top of the about section it would look like this:

Mock up 1.

As you continue to scroll through the various sections, they would scroll along side the nav bar, once reaching the top of the next section sitting at the top underneath the previous.

I've looked at Spyscroll but I haven't seen anything on the docs, nor any examples anywhere else of it having being responsive the the manor I described. Rather I see it being either on the section or off the section.

I'm just looking to be pointed in the right direction as I'm sure something like this is possible, unfortunately I'm quite new to web dev and you don't know what you don't know!

On a side note I'm also curious as to if this is a bad idea from a UI/UX standpoint as I haven't been able to find any examples of this.

Edit for clarity

I am not asking for help to fix broken code. I'm asking if what I'm looking to achieve is feasible and what I need to look into to create it.

If you're interested in seeing the code for the nav bar I created previously it is available here: Simple Navigation Bar


Solution

  • You can use Intersection Observer (IO) for this. With IO you can observe sections and react whenever they intersect with either each other or the viewport (that's what you want)

    First, you have to specify the options for IO:

    let options = {
      rootMargin: '-50px 0px -55%' // whatever suits your usecase, see documentation for this!
    }
    
    let observer = new IntersectionObserver(callback, options);
    

    then you define what elements you want to observe, something like:

    let entries = document.querySelectorAll('section');
    entries.forEach(entry => {observer.observe(entry);})
    

    Last step is to define what should happen if an element is intersecting:

    const observer = new IntersectionObserver(function (entries, self) {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
         //specify what should happen if an element is coming into view, like defined in the options. 
        }
      });
    }, config);