Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS browser scrolling bug

I'm having a vague bug while scrolling in a browser on an iOS device (iPad), it works 90% of the time but 10% it the scrolling is blocked. I then have to wait for a couple of seconds before it works again. This often happens after I've contracted/expanded a filter panel, which is also a scrollable component.

On all other devices, the scrolling is no issue whatsoever. I've looked everywhere on the internet but I couldn't find anyone with a similar problem?

My two scrollable components do have overflow-y: scroll and -webkit-overflow-scrolling: touch, but in general I highly doubt it's a CSS issue as it works most of the time, just not at random times.

I have tried adding onTouchStart={ () => {} } to my component, but also that doesn't solve it.

like image 444
Lydia Avatar asked Jan 11 '18 06:01

Lydia


2 Answers

I've come across this bug before. It seems to arise when setting elements to be the height of the browser viewport (e.g., height: 100vh). Try setting this on your <body> element:

body {
  position: relative;
}
like image 95
mfluehr Avatar answered Nov 12 '22 12:11

mfluehr


This problem is still here in iOs15, and I developed a small fix and put it on GitHub.

Complete code here: https://github.com/AlessandroCipolletti/fix-ios15-safari-scroll/blob/main/preventScrollBugsIfNeeded.ts

I noticed that the bug happens only when the scrollable content is "all on top" or "all at the end" of its scroll space.

I mean, when there is no scroll available in one of the two directions (top-bottom / left-right makes no difference for the occurrence of the bug).

So the idea is to check if this is the case during a touchstart event, and if so, make a 1px scroll by code.

I don't know why iOS "needs" this to make a proper scroll, but it works fine for me.

// do this inside a onTouchStart event handler:

const target = myScrollableContainer

// if it has vertical scroll
if (target.scrollHeight > target.clientHeight) {
  // if scroll is on top
  if (target.scrollTop === 0) {
    // move content 1px up
    target.scrollTop = 1
  } else 
  // if scroll in at the bottom
  if (target.scrollTop === (target.scrollHeight - target.clientHeight)) {
    // move content 1px down
    target.scrollTop = (target.scrollHeight - target.clientHeight) - 1
  }
}

// if it has horizontal scroll
if (target.scrollWidth > target.clientWidth) {
  // if scroll is at the beginning (left)
  if (target.scrollLeft === 0) {
    // move content 1px to the left
    target.scrollLeft = 1
  } else 
  // if scroll is at the end (right)
  if (target.scrollLeft === (target.scrollWidth - target.clientWidth)) {
    // move content 1px to the right
    target.scrollLeft = (target.scrollWidth - target.clientWidth) - 1
  }
}
like image 1
Alessandro Cipolletti Avatar answered Nov 12 '22 14:11

Alessandro Cipolletti