Div scrolling freezes sometimes if I use -webkit-overflow-scrolling
Asked Answered
B

7

66

if I use -webkit-overflow-scrolling for a scrolling div, it scrolls perfectly with native momentum. But, div itself sometimes freezes and does not respond my finger moves. After 2-3 seconds later, it becomes again scrollable.

I don't know how I am reproducing this problem. But, as I see there are two main behavior creates this situation.

First, If I wait for a while, for instance, 20 seconds, and touch the div, it does not respond. I wait a couple of seconds, and it becomes working again.

Second, I touch several times quickly, and then, it becomes freezing, and again, after a couple of seconds later, it starts working again.

How can I prevent this freezing?

Brief answered 25/9, 2016 at 22:13 Comment(13)
Can you try with forcing hardware acceleration? For example, if your scrolling div's class in element, use .element > * { -webkit-transform: translateZ(0px); } in your CSS.Pickar
Can you show your code? Or link to page where the issue?Resistor
Does it happen in all devices? Or there is a specific device/browser you're having this issue?Transnational
can you specify your browser and it's version above in the post?Impeachable
Did you try ThisImpeachable
I use iPhone 6s. I tried @GökhanKurt code, but it does not help. I think it is a OS bug for elements that have dynamic content. btw, this does not happen on Android devices. just of ios. I tried Safari and Chrome on iPhoneBrief
I have the exact problem right now. Have you ever manage to fix this issue and how?Suddenly
@Ahmed I. Elsayed !! Thank you so much. It worked like a charm.Opportina
Happy to hear that! :)Impeachable
@Resistor You asked for reproduction - here's the code, and here's the live demo. Just an overflowed fixed div with scroll and -webkit-overflow-scrolling enabled. Open the live demo link on an iOS device (I tried on iPhone 6 and on iPad mini 2, both running iOS 11.4.1), pull further at the top or at the bottom a few times to bounce the page, and there you have it, scrolling freezes for a few seconds. Disgusting.Turmeric
This is the relevant entry in the webkit bug tracker: bugs.webkit.org/show_bug.cgi?id=185614Turmeric
Hey Adem, did you get a solution for this.Prepotency
Another way to solve that issue is use the same approach of the Ionic framework and others similars: use a virtual scroll. It capture the touch events from do window and converts it to programmatically scroll on the div...Kurtz
P
19

For me, the freezing was repeatable and happened when trying to scroll up or down when already at the top or bottom, respectively. The fix was to add some listeners for touchstart and touchmove and detect these cases and event.preventDefault() on ’em.

Something like the following, where .scroller is the div that will actually scroll (changes to scrollTop).

var lastY = 0;
var targetElt = document.querySelector(".scroller");

targetElt.addEventListener('touchstart', function(event) {
    lastY = event.touches[0].clientY;
});

targetElt.addEventListener('touchmove', function(event) {
    var top = event.touches[0].clientY;

    var scrollTop = event.currentTarget.scrollTop;
    var maxScrollTop = event.currentTarget.scrollHeight -
        $(event.currentTarget).outerHeight();
    var direction = lastY - top < 0 ? 'up' : 'down';

    if (
        event.cancelable && (
            (scrollTop <= 0 && direction === 'up') ||
            (scrollTop >= maxScrollTop && direction === 'down')
        )
    )
      event.preventDefault();

    lastY = top;
});

I hope this helps the next poor soul that encounters this horrible bug! Good luck and keep fighting!

Philbrook answered 7/8, 2018 at 18:12 Comment(12)
This is the workaround that finally worked for me! Open in iOS Safari the live example and check out its code. The only downside is the glitchy absence of the bounce effect when already at the top/bottom, but it's acceptable and seems to be the the best option we have until WebKit maintainers fix the bug.Turmeric
@wesley , do we know, why this happens, as in this freeze when only at top or bottom.Prepotency
@Prepotency iOS Safari bug ¯_(ツ)_/¯, probably related to how it "bounces" when at top and bottom. Something about already being there, it probably kicks off the bounce affect and is non-responsive until that finishes but since you're already there it just bugs out.Philbrook
@WesleyReitzfeld Okay, got it. Is it kind of logged with them and they dont want to fix it.Prepotency
@Prepotency I don't know how to log it with them.Philbrook
@WesleyReitzfeld No worries. Your solution looked good and worked fine for me. Thanks.Prepotency
This errors for me - event.currentTarget.outerHeight is not a function. After resolving that it worked a treat thanks. I would edit the answer with the fix but as no one else has mentioned it I presume it worked for them. If anyone else runs into that it's because outerHeight is a jQuery method so you need to fire it on a jQuery element. Change to event.currentTarget.outerHeight() to $(event.currentTarget).outerHeight()Teacake
Please pay attention scrollTop <= 0 not top === 0, sometimes it is -1 and it freezes again :)Deidredeific
@MiheyMik ty, fixed!Philbrook
I had a bug with the exact same symptoms on Chrome/Firefox on Mac when scrolling in an <iframe>. Fixed it using tips from this post.Michelemichelina
Shouldn't outerHeight be changed to clientHeight? outerHeight by jQuery includes margin.Sulemasulf
For those not using jQuery in 2021.. You can replace el.outerHeight() with el.offsetHeight.Mathis
S
11

Try using overflow: hidden on body. This should resolve the issue: https://codepen.io/cppleon/pen/vYOgKzX

HTML

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  </head>
  <body>
    <div id="scrollable-content">
      <div class="site-header"></div>
      <div class="main-content"></div>
    </div>
  </body>
</html>

CSS

body {
  /* magic is here */
  overflow: hidden;
}

#scrollable-content {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 50%;
  background-color: gray;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.site-header {
  width: 100%;
  height: 120px;
  background-color: orange;
}

.main-content {
  height: 200%;
}
Surra answered 24/2, 2020 at 9:13 Comment(1)
Scroll freez is constantly reproducible on the iPhone when you do fast scrolling with tapping in the same time at the bottom nor at top and the scroll issue dissapears when scroll goes completely hidden. overflow: hidden in the body solved my problemDripps
H
5

Stable solution

After many days to try to fix it, i saw that the problem comes from fixed body element, maybe because you don't want your users to see your page body bounce when the scroll is blocked: cf this example. When the body is fixed and you're experiencing scrolling freeze bug, if you inspect the body with Desktop Safari on you iOS device, you can see it's kind of "artificially" moving... yes webkit stuff...

I tried all solutions listed on this threat but also on github similar issues. No one was working.

The only stable fix for me is to use this package : body-scroll-lock and remove the fixed on your body element. Right now you can both enjoy fixed body and no scrolling freezing bugs.

Hope it will help people who are currently creating progressive web apps on IOS.

Hallux answered 24/11, 2018 at 13:25 Comment(2)
How exactly are you using body-scroll-lock to prevent the freezing?Clincher
I apply it to every scrolling elementHallux
E
3

I used the below code I think is working.

var scrollTimer;
$('.scroller').on('scroll',function(e){
      clearTimeout(scrollTimer);
      scrollTimer = setTimeout(() => {
        this.scrollTop = Math.max(1, Math.min(this.scrollTop, this.scrollHeight - this.clientHeight - 1));
      }, 300);
});
Electret answered 24/8, 2018 at 6:29 Comment(1)
Wow: this is actually working for me so far. Would be nice to know how did you get to it.Vinnievinnitsa
S
1

I got the same problem. But that solved easily. This is what i have done: deleted height property of div that was scroll-able. Maybe you are not in the same situation as me and this will not work for you.

Singlebreasted answered 15/12, 2020 at 21:1 Comment(0)
E
0

I know this is very old, but maybe somebody else has the same problem. For me the issue was caused by iNoBounce (https://github.com/lazd/iNoBounce). Y scrolling was fine but X scrolling was causing a lot of issues, the element would get stuck and you'd have to touch and move many times until it finally scrolled.

After removing iNoBounce there were no issues anymore besides the obvious scroll-bounce (and specially the "overscrolling") that was iNoBounce removed. To disable the overscrolling I used the following, however the scroll-bounce is now there.

html { height: 100%; position: fixed; overflow: hidden; }
body { height: 100%; position: relative; overflow: auto; }
Evade answered 8/1, 2021 at 13:45 Comment(0)
M
0

I ran into this bug recently, and after trying a lot of hacky solutions the one that worked best for us was simply scrolling the view by a pixel if its at the bottom. This prevents the "freeze", which I think is actually the body/window receiving the scroll event if the nested container is fully scrolled down. This is using React but you get the idea.

const listener = () => {
    window.requestAnimationFrame(() => {
      if (!this.scrollRef.current) {
         return;
      }
   
      const { scrollTop, scrollHeight, clientHeight } = this.scrollRef.current;

      if (scrollTop === scrollHeight - clientHeight) {
          // at the bottom
          this.scrollRef.current.scrollTo(0, scrollHeight - clientHeight - 1);
      }
    });
}

this.scrollRef.current.addEventListener("scroll", listener);
Manyplies answered 17/4, 2021 at 17:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.