Prevent Scroll Bubbling from Element to Window

prevent Scroll bubbling from element to window

Solved (for some browsers) using a simple CSS property:
overscroll-behavior:

auto
The default scroll overflow behavior occurs as normal.

contain
Default scroll overflow behavior is observed inside the element this value is set on (e.g. "bounce" effects or refreshes), but no scroll chaining occurs to neighboring scrolling areas, e.g. underlying elements will not scroll.

none
No scroll chaining occurs to neighboring scrolling areas, and default scroll overflow behavior is prevented.

body{
height: 600px;
overflow: auto;
}

section{
width: 50%;
height: 50%;
overflow: auto;
background: lightblue;
overscroll-behavior: none; /* <--- the trick */
}

section::before{
content: '';
height: 200%;
display: block;
}
<section>
<input value='end' />
</section>

window scroll event – need prevent bubbling or not?

The third parameter useCapture specifies whether the event should be executed in the capturing or in the bubbling phase.

If it should be executed later than element event handlers, you have to use false(default).

If it should be executed earlier than element event handlers, you have to use true.

If no child elements have event listener, you can ignore the useCapture parameter.

Prevent scrolling of parent element when inner element scroll position reaches top/bottom?

It's possible with the use of Brandon Aaron's Mousewheel plugin.

Here's a demo: http://jsbin.com/jivutakama/edit?html,js,output

$(function() {

var toolbox = $('#toolbox'),
height = toolbox.height(),
scrollHeight = toolbox.get(0).scrollHeight;

toolbox.bind('mousewheel', function(e, d) {
if((this.scrollTop === (scrollHeight - height) && d < 0) || (this.scrollTop === 0 && d > 0)) {
e.preventDefault();
}
});

});

stopPropagation in scroll()-Method won't stop outer div from scrolling

the scroll event doesn't bubble so e.stopPropagation(); will not work

to prevent the scroll of the parent see:

Prevent scrolling of parent element?

How to prevent scroll event from firing after adjusting `scrollTop` when mouse pulls up scrollbar?

As mentioned in the comments, the fact that the event will keep on firing and logging that the div is at the top is a natural result from it being pushed down and then dragged up again rapidly because the scrollbar hasn't been released. As far as I can see, there's no direct way to cancel that interaction.

But without creating a custom scrollbar this is probably the quickest fix, even if it is a minor hack :

Demo

var wrapper = document.getElementById('scroll-box'),
size = wrapper.clientWidth;

wrapper.addEventListener('scroll', function() {

if (!wrapper.scrollTop) {
console.log('top of frame');
wrapper.scrollTop += 500;
wrapper.setAttribute('style', 'width: ' + size + 'px; overflow: hidden');
setTimeout(function() {
wrapper.removeAttribute('style');
}, 0);
}
});

wrapper.scrollTop += 200;

Eliminating the scroll event by hiding overflow for the shortest possible amount of time. And setting clientWidth of the element as well to make it keep it's original width so the action is less noticeble.

Disable outside scrolling while in scrollable div

Here's a FIDDLE

<div>
... some content ...
</div>

div {
height: 400px;
overflow: scroll;
}

$('div').on('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());
}
});

Scrolling child div scrolls the window, how do I stop that?

Found the solution.

http://jsbin.com/itajok

This is what I needed.

And this is the code.

http://jsbin.com/itajok/edit#javascript,html

Uses a jQuery Plug-in.


Update due to deprecation notice

From jquery-mousewheel:

The old behavior of adding three arguments (delta, deltaX, and deltaY)
to the event handler is now deprecated and will be removed in later
releases.

Then, event.deltaY must now be used:

var toolbox = $('#toolbox'),
height = toolbox.height(),
scrollHeight = toolbox.get(0).scrollHeight;

toolbox.off("mousewheel").on("mousewheel", function (event) {
var blockScrolling = this.scrollTop === scrollHeight - height && event.deltaY < 0 || this.scrollTop === 0 && event.deltaY > 0;
return !blockScrolling;
});

Demo

How to disable scrolling temporarily?

The scroll event cannot be canceled. But you can do it by canceling these interaction events:

Mouse & Touch scroll and Buttons associated with scrolling.

[Working demo]

// left: 37, up: 38, right: 39, down: 40,
// spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
var keys = {37: 1, 38: 1, 39: 1, 40: 1};

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

function preventDefaultForScrollKeys(e) {
if (keys[e.keyCode]) {
preventDefault(e);
return false;
}
}

// modern Chrome requires { passive: false } when adding event
var supportsPassive = false;
try {
window.addEventListener("test", null, Object.defineProperty({}, 'passive', {
get: function () { supportsPassive = true; }
}));
} catch(e) {}

var wheelOpt = supportsPassive ? { passive: false } : false;
var wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';

// call this to Disable
function disableScroll() {
window.addEventListener('DOMMouseScroll', preventDefault, false); // older FF
window.addEventListener(wheelEvent, preventDefault, wheelOpt); // modern desktop
window.addEventListener('touchmove', preventDefault, wheelOpt); // mobile
window.addEventListener('keydown', preventDefaultForScrollKeys, false);
}

// call this to Enable
function enableScroll() {
window.removeEventListener('DOMMouseScroll', preventDefault, false);
window.removeEventListener(wheelEvent, preventDefault, wheelOpt);
window.removeEventListener('touchmove', preventDefault, wheelOpt);
window.removeEventListener('keydown', preventDefaultForScrollKeys, false);
}

UPDATE: fixed Chrome desktop and modern mobile browsers with passive listeners



Related Topics



Leave a reply



Submit