54

I'm trying to disable the window mouse scroll functionality when the mouse is hovering over the div - so that only div scrolling is enabled - and when mouse moves away from the div - scrolling to the window is applied again. The div is positioned absolutely.

I've seen this post use jquery to disable mouse scroll wheel function when the mouse cursor is inside a div? but it doesn't seem to provide any answer - hence my question.

I'm assuming it would be something like this (if only these methods existed):

$('#container').hover(function() {
     $(window).scroll().disable();
     $(this).scroll().enable();
}, function() {
     $(window).scroll().enable();
});
Community
  • 1
  • 1
user398341
  • 5,629
  • 17
  • 52
  • 72
  • 1
    I'm having trouble understanding your question, isn't that the default behaviour? when you hover over a 'div' and you have 'overflow:scroll' the it just scrolls the 'div', other wise the window, or are you trying to make it so that, for example, when it's done scrolling, it still wont scroll the window? – Trufa Sep 27 '11 at 15:26
  • 1
    I suspect he is after exactly what you describe. His absolutely positioned div scrolls, but when it finishes scrolling he does not want the main window to scroll. This bugs me all the time when editing wordpress posts. Everything goes flying off the screen. When working in an editor it is nice if your work stays put! – mrtsherman Sep 27 '11 at 15:44
  • Yes - that's exactly what I meant - thanks @mrtsherman for clarifying this. – user398341 Sep 28 '11 at 15:09

6 Answers6

99

This has been a popular question so I am updating to give an overview of the answers provided here and which may be best for you. There are three unique solutions included. Two are from Amos and one is from myself. However, each operates differently.

  1. Amos - Set overflow:hidden on body. This is simple and works great. But the main window's scrollbars will flash in and out.
  2. Amos - Use javascript to disable mouse wheel. This is great if you don't need mousewheel at all.
  3. This answer - Use javascript to scroll only the element you are over. This is the best answer if your inner div needs to scroll, but you don't want any other divs to scroll. The example fiddle showcases this.

http://jsfiddle.net/eXQf3/371/

The code works as follows:

  • Catch scroll event on the current element
  • Cancel the scroll event
  • Manually scroll the current element only

 

$('#abs').bind('mousewheel DOMMouseScroll', function(e) {
    var scrollTo = null;

    if (e.type == 'mousewheel') {
        scrollTo = (e.originalEvent.wheelDelta * -1);
    }
    else if (e.type == 'DOMMouseScroll') {
        scrollTo = 40 * e.originalEvent.detail;
    }

    if (scrollTo) {
        e.preventDefault();
        $(this).scrollTop(scrollTo + $(this).scrollTop());
    }
});​

Changelog:

  • FF support
  • scrollTo null check to revert to default behavior in case something unforeseen happens
  • support for jQuery 1.7.
mrtsherman
  • 37,770
  • 19
  • 83
  • 106
  • 2
    @kunigami - I figured out what was wrong and updated my answer. `e.wheelDelta` was removed in jQuery 1.7 so I have to access it through `orginalEvent` instead. http://bugs.jquery.com/ticket/10676 – mrtsherman Feb 13 '12 at 06:56
  • here is a similar solution, using pure JS events rather than jQuery events: http://stackoverflow.com/questions/9256213/how-to-disable-scrolling-in-outer-elements/9256777#9256777 – ericsoco Feb 13 '12 at 07:15
  • 3
    @mrtsherman At first,thank you for the answer.But don't copy paster from jsFiddle. Above code will cause Unexpected token ILLEGAL in webkit which has some invalid (and unfortunately invisible) characters.see http://stackoverflow.com/questions/4404526/unexpected-token-illegal-in-webkit. – Mithril Nov 16 '12 at 08:33
  • Thanks! This worked like a charm for me in Chrome, Safari, Firefox and IE9. – claudiut Nov 29 '12 at 09:31
  • Thanks. Works beautifully here in Chrome, Firefox, IE9/8/7. Got that Unexpected token ILLEGAL in webkit and fixed it by pasting the code snippet in Notepadd++, removed the hidden '?' char and copy pasted the code into Visual Studio again. – PussInBoots Mar 10 '13 at 17:54
  • @ip. - works for me. You might want to double check your code. - http://jsfiddle.net/eXQf3/345/ – mrtsherman Jun 08 '13 at 19:28
  • Tried it again. Still doesn't work in FF. Any ideas why this could be? – ip. Jun 09 '13 at 00:59
  • @ip. - you tried that fiddle I posted and it failed? Or it is failing elsewhere? – mrtsherman Jun 09 '13 at 03:24
  • @mrtsherman yes I did, and it works fine in Chrome, Safari and Opera, in FF it fails - it first stops when you reach the end and then the page starts scrolling when you scroll in the div. – ip. Jun 09 '13 at 21:29
  • Thanks @mrtsherman hope soon the FF will get upgraded and the problem will solve :) – rkaartikeyan Nov 06 '13 at 00:04
  • the perfect solution great bro, i was disabling the scroll first and then using scrollTop for the current div and it was a lot of coding but yours is just great nice one bro +1 – Jeffery ThaGintoki Feb 24 '15 at 11:58
  • Beautiful hack love it. Other ways have messed up scroll bars. – joemillervi Sep 12 '17 at 06:55
31

You cannot disable window scroll, there is a simple workaround though:

//set the overflow to hidden to make scrollbars disappear
$('#container').hover(function() {
    $("body").css("overflow","hidden");
}, function() {
     $("body").css("overflow","auto");
});

See demo: http://jsfiddle.net/9Htjw/


UPDATE

You can disable the mouse wheel though.

$('#container').hover(function() {
    $(document).bind('mousewheel DOMMouseScroll',function(){ 
        stopWheel(); 
    });
}, function() {
    $(document).unbind('mousewheel DOMMouseScroll');
});


function stopWheel(e){
    if(!e){ /* IE7, IE8, Chrome, Safari */ 
        e = window.event; 
    }
    if(e.preventDefault) { /* Chrome, Safari, Firefox */ 
        e.preventDefault(); 
    } 
    e.returnValue = false; /* IE7, IE8 */
}

Source: http://solidlystated.com/scripting/javascript-disable-mouse-wheel/

Demo: http://jsfiddle.net/9Htjw/4/

amosrivera
  • 24,359
  • 9
  • 65
  • 76
  • It is working fine and got an issue when the div background is transparent.Will you please tell how to fix the issue. – Jomal Johny Dec 17 '18 at 04:45
3

mrtsherman: if you bind the event like this, amosrivera's code works also for firefox:

    var elem = document.getElementById ("container");
    if (elem.addEventListener) {    
        elem.addEventListener ("mousewheel", stopWheel, false);
        elem.addEventListener ("DOMMouseScroll", stopWheel, false);
    }
    else {
        if (elem.attachEvent) { 
            elem.attachEvent ("onmousewheel", stopWheel);
        }
    }
rocky
  • 6,724
  • 3
  • 31
  • 43
1

I used nicescroll on my page no method worked. I realized the nicescroller is calling the scroll event and had to temporarily disable nicescroll when hovering the element.

Solution: Temporarily disable nicescroll when hovering an element

$('body').on('mouseover', '#element', function() {
    $('body, html').css('overflow', 'auto').getNiceScroll().remove();
}).on('mouseout', '#element', function() {
    $('body, html').css('overflow', 'hidden').niceScroll();
});
Lasithds
  • 1,683
  • 21
  • 30
0

What I'm trying to do here with my code is:

  • Check if div is hovered over or moused over

  • Get the scroll direction

  • Compare the ScrollTop with the Height of the container and prevent further scroll when max or min is reached(until moused is out).

    var hovered_over = false;
    var hovered_control;          
    function onCrtlMouseEnter(crtl) {      //Had same thing used for mutliple controls 
        hovered_over = true;       //could be replaced with $(control).onmouseenter(); etc
        hovered_control = crtl;    //you name it
    }
    function onCrtlMouseLeave(crtl) {
        hovered_over = false;
        hovered_control = null;
    }
    
    $(document).on("mousewheel",function(e)
    {
       if (hovered_over == true) {                            
            var control = $(hovered_control);                 //get control
            var direction = e.originalEvent.wheelDeltaY;      //get direction of scroll
            if (direction < 0) {
                if ((control.scrollHeight - control.clientHeight) == control.scrollTop) {
                    return false;              //reached max downwards scroll... prevent;
                }
            }
            else if (direction > 0) {
                if (control.scrollTop == 0) {
                    return false;              //reached max upwards scroll... prevent;
                }
            }
        }
    });
    

http://jsfiddle.net/Miotonir/4uw0vra5/1/

Probably not the cleanest code and it can be improved upon easily, but this works for me. (control.scrollHeight - control.clientHeight) this part is kindoff questionable for me , but you should get the idea how to approach the problem anyways.

MjolTonir
  • 21
  • 3
0

@mrtsherman's Answer almost worked for me, but there was a breaking change with passive scrolling in Chrome.

preventScrollingEl = document.getElementById("WHATEVER");
preventScrollingEl.addEventListener('mousewheel', preventScrolling, {passive: false});
preventScrollingEl.addEventListener('DOMMouseScroll', preventScrolling, {passive: false});

function preventScrolling(event) {
  var scrollTo = null;

  if (event.type == 'mousewheel') {
    scrollTo = (event.wheelDelta * -1);
  } else if (event.type == 'DOMMouseScroll') {
    scrollTo = 40 * event.detail;
  }

  if (scrollTo) {
    event.preventDefault();
    $(this).scrollTop(scrollTo + $(this).scrollTop());
  }
}
Max Bileschi
  • 1,618
  • 2
  • 15
  • 18