Search code examples
jquerycssscrollscrollbarpreventdefault

Prevent page scrolling on button click with jQuery not CSS


I am trying to prevent the page from scrolling when the menu is open by way of clicking the hamburger icon. I do not want to use css because when I create the class "body.noScroll,html.noScroll{overflow: hidden}" it removes the scroll bar and causes the page to widen slitely causing the menu animation to jump and look like garbage. So CSS is a no go. I have searched this site and read multiple ways to try this. Mainly this page Just disable scroll not hide it?

1. My first attempt:

function lockScroll(e) {
  e.preventDefault();
}

$('.menuBtn').click(function(){
  if( $('.menu').hasClass('open') ){
    $('body').unbind('mousewheel touchmove', lockScroll);
    $('.menu').removeClass('open');
  }
  else{
    $('body').bind('mousewheel touchmove', lockScroll);
    $('.menu').addClass('open');
  }
});

But this gives me a jquery error:

"[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive"

2. My second attempt seems to work best but still has some issues:

CSS

body.noScroll{
  position: fixed;
  overflow-y: scroll;
}

jQuery

$('.menuBtn').click(function(){
  if( $('.menu').hasClass('open') ){
    $('body').css('top', - ($(window).scrollTop()) + 'px').removeClass('noScroll');
    $('.menu').removeClass('open');
  }
  else{
    $('body').css('top', - ($(window).scrollTop()) + 'px').addClass('noScroll');
    $('.menu').addClass('open');
  }
});

This will prevent scrolling when the menu is open but once you close the menu scrolling is re-enabled but it jumps back to the top of the page.

I have tried a 3rd attempt but it does the same as the second attempt(jumps back to the top of the page). Here is a fiddle with the three attempts I have tried - Fiddle

Any help on this is greatly appreciated.


Solution

  • Your 2. attempt is pretty close. Just keep the scroll position in a variable and scroll there after removing the class:

    let bodyScroll = 0;
    
    $('.menuBtn').click(function() {
      if ($('.menu').hasClass('open')) {
        $('body').removeClass('noScroll');
        // The inline styles are not needed anymore
        $('body').removeAttr('style');
        // Scroll back to the saved position
        $(window).scrollTop(bodyScroll);
        $('.menu').removeClass('open');
      } else {
       // Save current scroll position
       bodyScroll = $(window).scrollTop();
        $('body').css('top', -(bodyScroll) + 'px').addClass('noScroll');
        $('.menu').addClass('open');
      }
    });