0

I currently have a navigation that hides as you scroll down and then if you scroll up the navigation appears again.

I also have a class of .fixed on #top-wrapper which will change the layout/styling of this div. However when you get back to the top of the screen (threshold 200px) I want the class .fixed to be removed. I'm struggling to get it to detect this and then remove the class.

Here is a jsFiddle

(function () {

        var doc = document.documentElement;
        var w = window;

        var curScroll;
        var prevScroll = w.scrollY || doc.scrollTop;
        var curDirection = 0;
        var prevDirection = 0;

        var header = document.getElementById('top-wrapper');
        var toggled;
        var threshold = 200;

        var checkScroll = function () {
            curScroll = w.scrollY || doc.scrollTop;
            if (curScroll > prevScroll) {
                // scrolled down
                curDirection = 2;
            }
            else {
                //scrolled up
                curDirection = 1;
            }

            if (curDirection !== prevDirection) {
                toggled = toggleHeader();
            }

            prevScroll = curScroll;
            if (toggled) {
                prevDirection = curDirection;
            }
        };

        var toggleHeader = function () {
            toggled = true;
            if (curDirection === 2 && curScroll > threshold) {
                header.classList.add('hide');
                header.classList.add('fixed');
            }
            else if (curDirection === 1) {
                header.classList.remove('hide');
            }

            else if (curDirection === 1 && curScroll > threshold) {
                header.classList.remove('fixed');
            }
            else {
                toggled = false;
            }
            return toggled;
        };

        window.addEventListener('scroll', checkScroll);

    })();
body {
  padding:0; 
  margin:0;
}

main {
  min-height:20000px;
}

h1 {
  padding-top:40px;
}
#top-wrapper {
  width:100%;
  height:50px;
  background:red;
  position:fixed;
  top:0;
  transition: all 0.3s ease;
}

#top-wrapper.hide {
  top:-50px;
}

#top-wrapper.fixed {
  background:blue;
}
<main>
 <h1>
 IM THE TOP OF THE PAGE
 </h1>
<section id="top-wrapper"></section>

</main>
probablybest
  • 1,403
  • 2
  • 24
  • 47
  • Use `sticky` instead of `fixed`! Here's a potentially useful resource: https://www.w3schools.com/howto/howto_css_sticky_element.asp – Endothermic_Dragon Mar 22 '21 at 15:53
  • @Endothermic_Dragon Needs to be supported by more browsers so can't use sticky unfortunately. – probablybest Mar 22 '21 at 15:55
  • Then you could probably use some fancy JS that alternates `fixed` and another style. You can also use `scrollTop` or something - https://stackoverflow.com/questions/11373741/detecting-by-how-much-user-has-scrolled. – Endothermic_Dragon Mar 22 '21 at 15:55

2 Answers2

1

You need a separate if-else statement for each curDirection.

In your case when every curDirection === 1 used to be true the if-else statement used to stop there and thus it never reached curDirection === 1 && curScroll > threshold.

As you told you wanted it to work when it is less than the threshold and moving up. so now we have 2 different statement one for when curDirection === 1 and other for curDirection === 2.

(function() {
  var doc = document.documentElement;
  var w = window;

  var curScroll;
  var prevScroll = w.scrollY || doc.scrollTop;
  var curDirection = 0;
  var prevDirection = 0;

  var header = document.getElementById("top-wrapper");
  var toggled;
  var threshold = 200;

  var checkScroll = function() {
    curScroll = w.scrollY || doc.scrollTop;
    if (curScroll > prevScroll) {
      // scrolled down
      curDirection = 2;
    } else {
      //scrolled up
      curDirection = 1;
    }

    if (curDirection !== prevDirection) {
      toggled = toggleHeader();
    }

    prevScroll = curScroll;
    if (toggled) {
      prevDirection = curDirection;
    }
  };

  var toggleHeader = function() {
    toggled = true;

    if (curDirection === 2 && curScroll > threshold) {
      header.classList.add("hide");
      header.classList.add("fixed");
    } else {
      toggled = false;
    }

    if (curDirection === 1) {
      header.classList.remove("hide");
      if (curScroll < threshold) header.classList.remove("fixed");
    } else {
      toggled = false;
    }

    return toggled;
  };

  window.addEventListener("scroll", checkScroll);
})();
body {
  padding: 0;
  margin: 0;
}

main {
  min-height: 20000px;
}

h1 {
  padding-top: 40px;
}

#top-wrapper {
  width: 100%;
  height: 50px;
  background: red;
  position: fixed;
  top: 0;
  transition: all 0.3s ease;
}

#top-wrapper.hide {
  top: -50px;
}

#top-wrapper.fixed {
  background: blue;
}
<main>
  <h1>IM THE TOP OF THE PAGE</h1>
  <section id="top-wrapper"></section>
</main>
Manas Khandelwal
  • 3,790
  • 2
  • 11
  • 24
0

The problem is in your else if statements, your code will never reach this statement;

else if (curDirection === 1 && curScroll > threshold) {
  header.classList.remove('fixed');
}

Since the else if statement before it evaluates to true else if (curDirection === 1)

Here's the fixed code.

(function () {

        var doc = document.documentElement;
        var w = window;

        var curScroll;
        var prevScroll = w.scrollY || doc.scrollTop;
        var curDirection = 0;
        var prevDirection = 0;

        var header = document.getElementById('top-wrapper');
        var toggled;
        var threshold = 200;

        var checkScroll = function () {
            curScroll = w.scrollY || doc.scrollTop;

            // removing the fixed class
            if (curScroll < threshold)
                header.classList.remove('fixed');
            if (curScroll > prevScroll) {
                // scrolled down
                curDirection = 2;
            }
            else {
                //scrolled up
                curDirection = 1;
            }

            if (curDirection !== prevDirection) {
                toggled = toggleHeader();
            }

            prevScroll = curScroll;
            if (toggled) {
                prevDirection = curDirection;
            }
        };

        var toggleHeader = function () {
            toggled = true;
            if (curDirection === 2 && curScroll > threshold) {
                header.classList.add('hide');
                header.classList.add('fixed');
            }
            else if (curDirection === 1) {
                header.classList.remove('hide');
            }
            else {
                toggled = false;
            }
            
            return toggled;
        };

        window.addEventListener('scroll', checkScroll);

    })();
body {
  padding:0; 
  margin:0;
}

main {
  min-height:20000px;
}

h1 {
  padding-top:40px;
}
#top-wrapper {
  width:100%;
  height:50px;
  background:red;
  position:fixed;
  top:0;
  transition: all 0.3s ease;
}

#top-wrapper.hide {
  top:-50px;
}

#top-wrapper.fixed {
  background:blue;
}
<main>
 <h1>
 IM THE TOP OF THE PAGE
 </h1>
<section id="top-wrapper"></section>

</main>
Khalid Ali
  • 1,224
  • 1
  • 8
  • 12