Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS 11.3 bug - page scrolls while dragging #740

Open
levymetal opened this issue Apr 11, 2018 · 39 comments · Fixed by artsy/reaction#2924
Open

iOS 11.3 bug - page scrolls while dragging #740

levymetal opened this issue Apr 11, 2018 · 39 comments · Fixed by artsy/reaction#2924
Assignees
Labels

Comments

@levymetal
Copy link

levymetal commented Apr 11, 2018

#457 is back. iOS 11.3 using Safari, Flickity 2.1.1.

Seems to be a problem with iOS 11.3, not a regression in Flickity.

No test case required, the default CodePen demos the issue, as does the Flickity homepage
https://codepen.io/desandro/pen/azqbop
https://flickity.metafizzy.co

@desandro desandro added the bug label Apr 11, 2018
@desandro
Copy link
Member

Thanks for reporting this bug! Here's the deal:

iOS 11.3 uses passive event listeners by default. Flickity and its dependencies should use { passive: false } when adding event listeners. (Thx Stack Overflow). This will be coming in the next release.

HOWEVER, iOS 11.3.0 has Bug 184250, which breaks Flickity's behavior of using preventDefault on touchmove but not touchstart. Good news is that this bug has been addressed by WebKit lama Dean Jackson. You can add yourself to the CC list to the WebKit bug to help promote this issue.

For now, my options with iOS 11.3.0 are either prevent all scrolling when you touch inside a Flickity carousel, or keep current behavior, and allow page scrolling to occur with carousel dragging. I choose to keep current behavior.

Add a 👍 reaction to this issue if you ran into this issue as well so I can know how prevalent the issue is. Do not add +1 comments — They will be deleted.

Related: Shopify/draggable#198

@thekevbot
Copy link

I found a workaround for this using the dragStart and dragEnd events:

$carousel.on( 'dragStart.flickity', function( event, pointer ) {
    document.ontouchmove = function (e) {
        e.preventDefault();
    }
});
$carousel.on( 'dragEnd.flickity', function( event, pointer ) {
    document.ontouchmove = function (e) {
        return true;
    }
});

@desandro
Copy link
Member

WebKit Bug 184250 has been addressed, received a patch, and is now listed as Resolved. Keep an eye on this bug and future Safari releases to see when this patch lands.

@danazkari
Copy link

Hello @desandro!

So I'm working on a project where we're using this amazing library, and we were wondering if you've gotten any further insight on this issue about WebKit, their bug page doesn't say too much about the plan on that specific patch.

Thanks!

@desandro
Copy link
Member

Sorry, I don't have any insights on updates with this bug at the moment. Anyone with iOS 11.4 installed care to report?

@Spone
Copy link

Spone commented Jul 13, 2018

I just upgraded to iOS 11.4.1 and I still have the issue.

@datune
Copy link

datune commented Aug 8, 2018

Same issue on both iOS Chrome and Safari.

@desandro Is it possible to implement an option so we can choose where to enable / disable the behaviour?

@desandro
Copy link
Member

desandro commented Aug 8, 2018

Good news! From Comment 31 on WebKit bug 184250

The fix should be included in the iOS 12 betas.

So when iOS 12 goes out, hopefully this will be resolved.

@xcrap
Copy link

xcrap commented Aug 27, 2018

Just to tell I'm using iOS 12.0 (Beta 8) and still have this issues.

@alexbouchardd
Copy link

alexbouchardd commented Sep 20, 2018

Also seeing the issue in the public release of iOS 12. Just to make sure we are talking about the same issue, here is a video:

https://drive.google.com/file/d/1X6A9Rd9DtAQ6OvkQ-liLcRK8QnSd6PDf/view?usp=sharing

@datune
Copy link

datune commented Sep 20, 2018

Confirmed. It is not fixed in iOS 12, which really, like, really sucks. Not even the very latest Chrome on iOS12 makes any difference. @desandro Is there nothing we can do?

@SamHall
Copy link

SamHall commented Oct 24, 2018

I solved it by enclosing the carousel in the div id "flick" and added this code:

document.getElementById("flick").addEventListener('touchmove', function(e) { e.preventDefault(); }, { passive: false });

@jatinwaichal
Copy link

Hi all,
Is there an update on this issue?
I am still facing the issue on iOS 12

@AlexandraKlein
Copy link

@jatinwaichal which solve have you implemented? Mine works perfectly for me.

@alexbouchardd
Copy link

alexbouchardd commented Nov 27, 2018

@AlexandraKlein Solution worked perfectly fine for me as well. Had to tweak it slightly because I am not using jquery

// this.flkty = new Flickity(element)
this.flkty.on('dragStart', () => (document.ontouchmove = e => e.preventDefault()));
this.flkty.on('dragEnd', () => (document.ontouchmove = () => true));

@sheriffderek
Copy link

Ok. So, I'm not crazy? This is good news. : )

I always have such a great experience with Flickity - but in this latest project / I'm definitely feeling whatever this iOS change is.

I was doing some comparisons here: code: https://codepen.io/pxlagency/pen/xmbJyw?editors=0010
And I've added @alexbouchardd 's and @SamHall 's solutions / but I can't tell if it's working as expected. The first one seems to completely disable scrolling in that area / which is rough if you have a slider that takes up most of the screen / and I can't tell if the second one is helping.
For viewing on phone: https://s.codepen.io/pxlagency/debug/xmbJyw

In our actual project / we're using vue-flickity / but that wouldn't really change anything - and is why I made this example in a sandbox.

Any ideas?

@markdavies
Copy link

The dragStart / dragEnd fix doesn't work for me on Safari iOS12. Is there no way around this at all?

@Yakoot
Copy link

Yakoot commented Feb 19, 2019

any ideas how to fix it?

@desandro desandro self-assigned this Feb 25, 2019
@chessydk
Copy link

Btw, a comment in the original IOS bug (Bug 184250), which is now closed, mentions another related IOS bug which has no fix-plans yet: https://bugs.webkit.org/show_bug.cgi?id=185656 and could cause similar problem. So for this reason I hope this bug will receive high priority (the workarounds suggested are also not working for me on IOS 12.1.4)

@alex-figge-schuster
Copy link

Any solution how to handle this iOS bug by flickity? Can't you detect the scroll direction and block or allow vertical page scroll?

@SamHall
Copy link

SamHall commented Mar 12, 2019

My 10/23/18 post appears to work. I didn't end up using the page, but it's live and you can see it here:
https://chattanoogahistory.com/gallerynew5

@alex-figge-schuster
Copy link

@SamHall thank you. Your solution seems to work in your case, but it won't work if you have a fullpage flickity instance (or at least one which takes up most of the viewport). In this case you can't scroll the page because every vertical scroll gets picked up by your implementation. I would need a solution which allows vertical page scroll by detecting the scroll direction(s) and the scroll distance.
So, when a users starts scrolling at 200, 100 (x, y) and scrolls to 220, 200 it should assume that the user want's to scroll vertical (so flickity should not grap the scrolling event respectively pass it through). But when the user starts at 200, 100 and scrolls to 280, 90 for example, flickity should grap the event.

@SamHall
Copy link

SamHall commented Mar 12, 2019

Thank you for clarifying ‘vertical page scroll’.

@woahdae
Copy link

woahdae commented Mar 19, 2019

I've got a workaround / temporary fix.

The bug referred to up top (iOS 11.3.0 Bug #184250) is about event.preventDefault() not working for event listeners registered while inside another event listener. Flickity does just this, adding and removing a touchmove listener from inside touchstart/touchend listeners. It doesn't have to be that way - you could listen to all touchmove events and not do anything if you don't need to.

Anyways, I don't have the time/desire to refactor Flickity for a workaround, and the maintainers might not want that either. Here's a bit of code that will block vertical scrolling inside .carousel-cell elements if the swipe is also somewhat horizontal (using Flickity.defaults.dragThreshold):

https://gist.github.com/woahdae/aa579f1eced44fb89e8fd1b7183d67de

;(function() {
  var touchingCarousel = false
    , touchStartCoords

  document.body.addEventListener('touchstart', function(e) {
    if (e.target.closest('.carousel-cell')) {
      touchingCarousel = true
    } else {
      touchingCarousel = false
      return
    }

    touchStartCoords = {
      x: e.touches[0].pageX,
      y: e.touches[0].pageY
    }
  })

  document.body.addEventListener('touchmove', function(e) {
    if (!(touchingCarousel && e.cancelable)) return

    var moveVector = {
      x: e.touches[0].pageX - touchStartCoords.x,
      y: e.touches[0].pageY - touchStartCoords.y
    }

    if (Math.abs(moveVector.x) > Flickity.defaults.dragThreshold)
      e.preventDefault()

  }, {passive: false})

  // Polyfill for Element.closest
  // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
  if (!Element.prototype.matches) {
    Element.prototype.matches =
      Element.prototype.msMatchesSelector ||
      Element.prototype.webkitMatchesSelector
  }

  if (!Element.prototype.closest) {
    Element.prototype.closest =
      function(s) {
        var el = this

        do {
          if (el.matches(s)) return el
          el = el.parentElement || el.parentNode
        } while (el !== null && el.nodeType === 1)
        return null
      }
  }
})();

(the above is written for clarity, not OO best practices etc)

@Ross7377
Copy link

Ross7377 commented Apr 22, 2019

Works perfect for me

            var tapArea, startX ;
            tapArea = document.querySelectorAll('.gallery');
            startX = 0;
            for (var item of tapArea) {
                item.ontouchstart = function(e) {
                    startX = e.touches[0].clientX;
                };
                item.ontouchmove = function(e) {
                    if (Math.abs(e.touches[0].clientX - startX) > 5 && e.cancelable ) {
                        e.preventDefault();
                    }
                };
            }

@wilbertcaba
Copy link

@Ross7377 It worked for me too. Thanks for the temporary fix!

@wilbertcaba
Copy link

wilbertcaba commented Apr 30, 2019

Works perfect for me

            var tapArea, startX ;
            tapArea = document.querySelectorAll('.gallery');
            startX = 0;
            for (var item of tapArea) {
                item.ontouchstart = function(e) {
                    startX = e.touches[0].clientX;
                };
                item.ontouchmove = function(e) {
                    if (Math.abs(e.touches[0].clientX - startX) > 5 && e.cancelable ) {
                        e.preventDefault();
                    }
                };
            }

@Ross7377 However, for the heads up, this is breaking Flickity on IE11. I had to wrap it in conditional comments:

<!--[if !IE]-->[your script...]<!--<![endif]-->

@timothyallan
Copy link

Yeah, you'd need to use a for loop, or polyfill the for ... of loop.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

@davidhellmann
Copy link

iOS 13 it looks fine here. iOS 12 we also have the problem. We have the solution from @thekevbot included but doesn't work.

@saetia
Copy link

saetia commented Sep 6, 2019

adding this css fixes the issue on iOS 13:

.slider {
    touch-action: none; -webkit-user-select: none; -webkit-user-drag: none;
}

@davidhellmann
Copy link

@saetia yes but with this css you cant scroll Y-axis.

@seansmyth
Copy link

Seems to be an issue on Firefox on Android for me.

@andrey-scada
Copy link

andrey-scada commented Jul 3, 2020

@Ross7377, thank you so much for your solution!

@vasanthangel4
Copy link

@andrey-scada: scrolling issue happened in ios 15, dots also not working

@vasanthangel4
Copy link

Hi all, if anyone have fixed the iOS 15 issue

@vasanthangel4
Copy link

Hi all,
Is there an update on this scroller issue in iOS 15
I am still facing the issue on iOS 15

@bansavage
Copy link

@woahdae 's fix is working for me today (may 2022)

@gregg-cbs
Copy link

I hope someone comes up with a better fix for this issue soon :)

@gregg-cbs
Copy link

I am wondering if something like this will work?

// stop page from scrolling when swiping flickity
let scrollY;

flkty.on('dragStart', () => {
  scrollY = window.scrollY;
});

flkty.on('dragMove', () => {
  window.scrollTo(0, scrollY)
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging a pull request may close this issue.