40

Any insights on how to catch a scrolling event on a element that has overflow:hidden? I would like to scroll in a column without showing a scrollbar to the user.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Markus Jönsson
  • 655
  • 1
  • 6
  • 7

6 Answers6

35

This is actually a somewhat indepth process. What I do is set global flags when users mouse enters and leaves the element that you want to scroll. Then, on the mousewheel event for the body I check to see if the MOUSE_OVER flag is true, then stop propagation of the event. This is so the main body doesnt scroll in case your entire page has overflow.

Note that with overflow hidden, the default scrolling ability is lost so you must create it yourself. To do this you can set a mousewheel listener on your div in question and use the event.wheelDelta property to check whether the user is scrolling up or down. This value is different according to browser, but it is generally negative if scrolling down and positive if scrolling up. You can then change position of your div accordingly.

This code is hacked up quickly but it would essentially look like this...

var MOUSE_OVER = false;
$('body').bind('mousewheel', function(e){
  if(MOUSE_OVER){
    if(e.preventDefault) { e.preventDefault(); } 
    e.returnValue = false; 
    return false; 
  }
});

$('#myDiv').mouseenter(function(){ MOUSE_OVER=true; });
$('#myDiv').mouseleave(function(){ MOUSE_OVER=false; });

$('#myDiv').bind('mousewheel', function(e){
  var delta = e.wheelDelta;
  if(delta > 0){
    //go up
  }
  else{
    //go down
  }
});
vivekkupadhyay
  • 2,851
  • 1
  • 22
  • 35
anson
  • 4,156
  • 2
  • 22
  • 30
  • 3
    I didnt mention but you should look into `event.wheelDelta` and `event.detail` to fine tune things. Firefox uses `event.detail` while others use `event.wheelDelta` and using these values you can figure out some velocity control if you wanted to go that complex. This link will help http://www.javascriptkit.com/javatutors/onmousewheel.shtml – anson Dec 04 '11 at 22:46
  • 1
    The mousewheel event does not work any longer. It is called wheel in modern browsers. – netAction Oct 12 '15 at 13:42
  • 1
    To follow up @netAction's comment about using `wheel` instead of `mousewheel`: https://developer.mozilla.org/en-US/docs/Web/Events/wheel – ericsoco Jan 27 '16 at 19:27
  • Got this working in chrome by calling e.originalEvent.wheelDelta instead – Doa Nov 30 '16 at 05:04
  • Listening to the `wheel` event will give you the wrong scroll direction on OSes with inverted scrolling. – Design by Adrian Jul 03 '19 at 07:53
4
$("body").css("overflow", "hidden")

$(document).bind('mousewheel', function(evt) {
    var delta = evt.originalEvent.wheelDelta
    console.log(delta)
})

works for me. adapted from How do I get the wheelDelta property?

Community
  • 1
  • 1
Neil
  • 81
  • 1
  • 6
3

I use overflow:scroll, but also Absolutely position a div over the scroll bar in order to hide it.

maxedison
  • 17,243
  • 14
  • 67
  • 114
  • Thanks! Might be a good last resolution if I can't find any other solution. Feels a bit ugly way to solve it though. – Markus Jönsson Dec 04 '11 at 20:34
  • 1
    Sure, it's a trick, but a very elegant one in my opinion. I had actually started to write up a response like @andbeyond's, but then this CSS trick occurred to me. It's far simpler than the JS method, which means not only easier to implement but less bug-prone. – maxedison Dec 05 '11 at 13:06
  • Yea, that one actually works a lot better than my experiments on binding the scroll event to moving an element. I'll try this way as well and see how it goes. Thanks for the example! :) – Markus Jönsson Dec 05 '11 at 15:58
  • While I like this idea and intend to file it away for future reference, it's worth noting that this solution will only work with a solid background. Demo: http://jsfiddle.net/cghzb/ – slooooowdown Feb 18 '13 at 00:01
  • This won't work cross-browser, different browsers position and show the scrollbar differently. – Etheryte Oct 23 '15 at 12:47
2

I edited @anson s answer to Vanilla Javascript since it may be useful for others. Also note that "mousewheel" event is deprecated. So my code uses "wheel" instead. Next to that I added arrow functions for practical access the to "this".

fixScrollBehavior(elem) {
                elem.addEventListener('scroll', (e) => {
                    console.log('scrolling');
                });

                let MOUSE_OVER = false;
                elem.addEventListener('wheel', (e) => {
                    if (MOUSE_OVER) {
                        if (e.preventDefault) {
                            e.preventDefault();
                        }
                        e.returnValue = false;
                        return false;
                    }
                });

                elem.addEventListener('mouseenter', () => {
                    MOUSE_OVER = true;
                });
                elem.addEventListener('mouseleave', () => {
                    MOUSE_OVER = false;
                });

                elem.addEventListener('wheel', (e) => {
                    let delta = e.wheelDelta;
                    if (delta > 0) {
                        //go up
                    } else {
                        //go down
                    }
                });
            }

Note that this does not fix the mobile touch-"scroll"s.

Frizzant
  • 684
  • 1
  • 7
  • 28
1
$("div").on('wheel', function (e) {
        if (e.originalEvent.deltaY < 0) {
        console.log("Scroll up");
    } else {
        console.log("Scroll down");
    }
});

This did the trick for me. JSFiddle

StackFiddle:

$("div").on('wheel', function(e) {
  if (e.originalEvent.deltaY < 0) {
    console.log("Scroll up");
  } else {
    console.log("Scroll down");
  }
});
div {
  height: 50px;
  width: 300px;
  background-color: black;
  overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div></div>
Nebulosar
  • 1,727
  • 3
  • 20
  • 46
0

I am late, but I think I have a better answer.

Style your container as overflow: overlay, this will free up space of scrollbar, then style scrollbar or hide it or make its handle height/width 0,

Then you should get scroll events also.

Note : styling the scrollbar is not supported in all web browsers.

Meet Bhalodiya
  • 630
  • 7
  • 25