17

The question is so long that coming up with a title that summarises it proved tricky.

So anyway. I have a div that has overflow: auto and that frequently does flow over so the scrollbar appears. Then I have a div that has position: fixed and is positioned on top of the content div.

Now when I have a fixed-positioned div over the html body itself, I can scroll the document with the wheel when I have my mouse over the div. Not so lucky with the aforementioned div.

Is there a way to scroll the div "through" the fixed-positioned one?

I noticed that even catching the scroll event when over the fixed div isn't easy; the event isn't fired unless the fixed div itself is scrollable.

I made a simple jsFiddle here and for your convenience stripped it of all the JavaScript I tried.

Edit: I need to retain other mouse functions with the fixed div so turning pointer-events off isn't the solution in my case.

Antti29
  • 2,953
  • 12
  • 34
  • 36

4 Answers4

29

What you are looking for is pointer-events: none;

This makes the pointer not interact with that div essentially, so just do

#fixed {
  pointer-events: none;
}

DEMO

And you will get your desired outcome with no JS required. This will stop all other interaction with the div though, if you need to interact with it for some reason I'm afraid you'll have to look into a JS solution.

Andy
  • 14,427
  • 3
  • 52
  • 76
  • 2
    Ah, forgot to mention that. The fixed div isn't there for decoration, it does have some mouse-related functionality I can't afford to lose. Excellent answer anyway, even though it doesn't solve my problem I'm certain it'll be useful to others. – Antti29 Nov 21 '12 at 14:06
  • 1
    Be aware that this isn't fully cross-browser either. – Steffan Donal Nov 21 '12 at 14:08
  • 2
    Indeed - currently not supported in IE or Opera (http://caniuse.com/#feat=pointer-events) – Andy Nov 21 '12 at 14:09
  • +1, I had never heard of it, and it might come in handy somewhere – Abhilash Nov 21 '12 at 14:12
  • does anybody know whether it helps to improve animations performance, specifically FPS, e.g. if i disable interaction of most of the elements on the page with the method proposed in this post? P.S. i am talking about common issues on Parallax sites. – Anonymous Jun 12 '14 at 14:10
  • Works like a charm! Even in the newest versions of IE, Chrome, Firefox, Safari and Opera.. http://caniuse.com/pointer-events – Memet Olsen Jul 24 '14 at 15:04
  • Awesome, I didn't know about this property. Kudos for you! – Rorok_89 Nov 09 '15 at 11:20
  • I just realized that if you set this property on the fixed div that acts as a mask in my case, the user can now click through it on the underlying elements, which defies the purpose :( – AsGoodAsItGets Jun 27 '17 at 14:01
18
var fixedElement = document.getElementById("fixed");

function fixedScrolled(e) {
    var evt = window.event || e;
    var delta = evt.detail ? evt.detail * (-120) : evt.wheelDelta; //delta returns +120 when wheel is scrolled up, -120 when scrolled down
    $("#content").scrollTop($("#content").scrollTop() - delta);
}

var mousewheelevt = (/Gecko\//i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
if (fixedElement.attachEvent)
    fixedElement.attachEvent("on" + mousewheelevt, fixedScrolled);
else if (fixedElement.addEventListener)
    fixedElement.addEventListener(mousewheelevt, fixedScrolled, false);

jsFiddle Demo - Scroll!

Brad Adams
  • 2,066
  • 4
  • 29
  • 38
Steffan Donal
  • 2,244
  • 4
  • 24
  • 47
12

I came up with a more elegant solution, however as it was Ruirize's answer that got me to the right track I gave him the accept tag.

$('#fixed').on('mousewheel DOMMouseScroll', function(event) {
    $('#content').scrollTop($('#content').scrollTop() - (event.originalEvent.wheelDelta || -event.originalEvent.detail*30));
});

It is also displayed at jsFiddle.

Antti29
  • 2,953
  • 12
  • 34
  • 36
  • 2
    This solution is indeed more elegant and more readable. I would prefer to see it as the accepted answer. – Lars Blumberg May 17 '13 at 13:32
  • This solution isn't necessarily more elegant, it just uses jQuery - but upvotes for both answers, this is what I came here for! – Jesse Jun 25 '13 at 18:05
  • By elegance I was referring to the much fewer lines of code in my answer (and arguably the better readability). As to jQuery — I had tagged the question with it and the other answer also uses it. Both solutions appear to work; use them at your own discretion :) – Antti29 Jun 28 '13 at 07:23
2

While the accepted answer definitely will get you the result you need, there is a noticeable difference in the smoothness of scrolling naturally and the scrolling triggered by setting scrollTop. This utilizes the best parts of pointer-events: none; without actually removing the ability to interact with your fixed elements.

function enableScroll(e) {
  var self = $(this);
  self.css('pointer-events', 'none');
  clearTimeout(this.timer);
  this.timer = setTimeout(function () {
      self.css('pointer-events', 'all');
  }, 100);
}
$('#fixed').on('mousewheel DOMMouseScroll', enableScroll);