0

I am trying to add a class to my sticky container once the user scrolls the page past 100px, but it is lagging, and toggling the class uncontrollable.

$(function () {

    $nav = $(".topmenu-container");
    $(document).scroll(function () {
        if ($(this).scrollTop() >= 100) {
            $nav.addClass('scrolled');
        } else {
            $nav.removeClass('scrolled');
        }

    });
});

This is what I have so far.. I had the same function without an if clause and the toggleClass function instead, but same effect there.

Here you see the container that sticks to the top on scroll, and that I want to add the class to once the user scrolls past 100px from top for example

Edit: I now output the scrollTop value and saw, that it seems to get stuck at the point where the toggle should happen. It keeps jumping between 156px and 87px which makes the toggle happen multiple times a second. Does anyone have an idea?

  • Code seems to work fine: https://jsfiddle.net/RoryMcCrossan/q8v7g49o/. Can you be more specific about the issue? – Rory McCrossan Jan 17 '22 at 15:29
  • The code should should work quite fine. Although, in my experience, it is preferable to set scroll listeners on $(window). Try with $(window).on('scroll', function(){}) instead of $(document).scroll(function () {}). – Marghen Jan 17 '22 at 15:40
  • @RoryMcCrossan Yeah, I can't scroll past the limit where I toggle the class i.e 100px. It keeps toggling like crazy. – Fewture Webdesign Jan 17 '22 at 18:13

2 Answers2

0

What you need is rate limiting for your scroll events. In your case, I would suggest throttling, which means that your scroll events are limited to a certain number per second or time unit.

Another option is to use debouncing, but this would cause the event to be triggered only once at the end of the scrolling, which might not be the best solution for your case.

Read more here: Difference Between throttling and debouncing a function

Nice visualization: http://demo.nimius.net/debounce_throttle/

gru
  • 2,319
  • 6
  • 24
  • 39
0

Depending on your use case you may actually get away with the new sticky value for the position property in CSS: https://developer.mozilla.org/en-US/docs/Web/CSS/position

Additionally, instead of using debouncing and throttling, you could consider using the IntersectionObserver API. The events for InteresectionObserver fire only once (depending on settings) and surely less than scroll which is a hard to optimize event since it fires all of the time. See here: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

Now, if you have some elements inside the element that depend on the class, such as... the logo having a scaling animation or such, you will definitely have to use IntersectionObserver. It looks like your threshold is 100 pixels, you can definitely configure Interesction Observer to do that.

You can also take a look at this example from Wes Bos which seems to be in one of his free classes: https://wesbos.com/javascript/06-serious-practice-exercises/scroll-events-and-intersection-observer

I'm hoping you can try these solutions instead of the antiquated scroll thing.

Dharman
  • 30,962
  • 25
  • 85
  • 135