Don Rhummy
Don Rhummy

Reputation: 25810

iOS Safari appears to never fire scroll event if the element under mouse has only "overflow-y: scroll" and scrolling horizontally

I have two elements, a parent node and child. The child is scrollable only vertically (overflow: hidden; overflow-y: scroll;). The parent can be scrolled only horizontally (overflow: hidden; overflow-x: scroll;). When I swipe sideways over the child node, no scroll event is ever fired despite doing this:

//NEITHER of these are fired when swiping sideways on the child
child.addEventListener( "scroll", listener, true );
parent.addEventListener( "scroll", listener2, true );

The browser only fires a scroll event if I scroll vertically while over the child! Neither listener nor listener2 is ever called! How do I get it to fire a horizontal scroll for a parent element if the child element has only one direction scrolling?

Fiddle Mobile Example: https://jsfiddle.net/cn2hfLok/2/embedded/result/

HTML:

<div class="parent">
    <div class="child">
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
        content<br />content<br />content<br />content<br />content<br />content<br />content<br />
    </div>
    <div style="width: 5000px;">s</div>
</div>

CSS:

.parent
{
    position:relative;
    width: 600px;
    height: 100%;
    background-color: yellow;
    overflow: hidden;
    overflow-x: scroll;
}

.child
{
    position:relative;
    width: 50%;
    height: 200px;
    background-color: blue;
    overflow: hidden;
    overflow-y: scroll;
}

JavaScript:

function scrollC(e)
{
    console.log( "child" );
}

function scrollP(e)
{
    console.log( "parent" );
}

document.querySelector( ".child" ).addEventListener( "scroll", scrollC );
document.querySelector( ".parent" ).addEventListener( "scroll", scrollP );

EDIT: It appears even with overflow: scroll on the child, if there's nothing to scroll horizontally, it still won't fire a scroll event! https://jsfiddle.net/cn2hfLok/4/embedded/result/

Upvotes: 2

Views: 3249

Answers (2)

Don Rhummy
Don Rhummy

Reputation: 25810

It is impossible to capture a scroll event on iOS Safari for the parent if the child has nothing to scroll in the direction you're attempting to move or it doesn't listen to that direction. To overcome this, you need to listen to touch events on the child and then pass that movement on to the parent by changing the parent's scrollLeft or scrollTop which will fire the parent's scroll event handler.

Listen to:

touchstart

capture the starting position

touchmove

check the current position against the start, if it moves horizontally (and little enough vertically), then pass to the parent by parent.scrollLeft += startX - e.clientX; and then call e.stopPropagation();e.preventDefault(); so it doesn't move the page. (Also update your startX to be the e.clientX)

touchend and touchleave

Set some variable to tell your touchmove handler to stop listening, for example notDragging = true;

Upvotes: 3

Dmytro Hutsuliak
Dmytro Hutsuliak

Reputation: 1751

I think you should move in the following direction:

  1. Enable the capturing phase for a handler: document.querySelector( ".parent" ).addEventListener( "scroll", scrollP, true );

  2. Stop propagation in the parent callback: e.stopPropagation();

In this case the parent's listener will intercept all events including horizontal scroll. But actually you can filter them by event.type and a bunch of other accessible properties.

Here's the updated example: https://jsfiddle.net/cn2hfLok/7/

Upvotes: 0

Related Questions