20

iOS 15 is out and so is the new release of Safari that brings the ubiquitous pull-to-refresh. Like it or not, single-page apps don't like that too much.

Here's how to disable it on Chrome for iPhone:

Disable Chrome's pull-to-refresh on iPhone

Any idea how to do the same in Safari in iOS 15?

The CSS overscroll-behavior-y: contain has no effect.

VH-NZZ
  • 5,248
  • 4
  • 31
  • 47
  • 4
    it looks like apple screwed us again.. preventing the document or body from scrolling does not seem possible anymore, see https://pqina.nl/blog/how-to-prevent-scrolling-the-page-on-ios-safari/, note that the body scroll lock demo does not work anymore on iOS 15: https://bodyscrolllock-modal.vercel.app – phil_lgr Oct 04 '21 at 20:47
  • 2
    Have you found a solution? This makes our mobile web app so much worse now. – Alex Fox Oct 08 '21 at 14:29
  • 2
    Not really an answer, but on iOS 16 overscroll-behavior: none does prevent this. It's not a good solution since it also prevents overscroll entirely, which makes scrollers feel very unnatural on iOS, but if you're desperate for a workaround, that seems to be all there is. I'm not sure how they thought to add overscroll-behavior, but forgot to add an "overscroll but don't refresh" value, which is what's almost always wanted. – Glenn Maynard Nov 10 '22 at 04:05

6 Answers6

15

Very crude solution that worked for our use case is to set an overflow: hidden; to the body element, but then you need to have an overflowing container element for all the content, otherwise scroll is blocked.

<body>
    <div id="container"> Content </div>
</body>
body {
    overflow: hidden;
}

#container {
    height: 100vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
Tina Cho
  • 159
  • 4
  • This works great, thank you! In my case, I already set the height of #container to something else, so height:100vh; is not needed. – rakensi Oct 18 '21 at 09:40
  • This actually worked for me, and didn't have a bunch of hacky JS event handlers that caused lots of side effects within the app. No side effects here! – Kevin Baragona Dec 19 '21 at 18:36
  • This works for my website when iOS 15 safari is in "Tab Bar" mode (Settings > Safari > Tabs), but when it's in "Single Tab" mode, pull-to-refresh behavior returns. Does anyone else see the same behavior? – Dave Peck Jan 05 '22 at 01:22
  • Perfect! This worked like a charm for my use case!!! Thanks a bunch, you saved me a lot of headache!!! – Christian Feb 11 '22 at 09:27
9

In 2022, this works nicely for me:

body {
  overflow: hidden;
}
oldboy
  • 5,729
  • 6
  • 38
  • 86
CaptainStiggz
  • 1,787
  • 6
  • 26
  • 50
7

I disabled this behaviour by setting the CSS property touch-action of the target element to none.

touch-action:none;

https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action

Elias Dörig
  • 141
  • 1
  • 3
4

Here is the tricky part:

/* prevent pull-to-refresh for Safari 16+ */
@media screen and (pointer: coarse) {
  @supports (-webkit-backdrop-filter: blur(1px)) and (overscroll-behavior-y: none)  {
    html {
      min-height: 100.3%;
      overscroll-behavior-y: none;
    }
  }
}
/* prevent pull-to-refresh for Safari 9~15 */
@media screen and (pointer: coarse) {
  @supports (-webkit-backdrop-filter: blur(1px)) and (not (overscroll-behavior-y: none))  {
    html {
      height: 100%;
      overflow: hidden;
    }
    body {
      margin: 0px;
      max-height: 100%; /* or `height: calc(100% - 16px);` if body has default margin */
      overflow: auto;
      -webkit-overflow-scrolling: touch;
    }
    /* in this case to disable pinch-zoom, set `touch-action: pan-x pan-y;` on `body` instead of `html` */
  }
}

/* prevent pull-to-refresh for Chrome 63+ */
body{
  overscroll-behavior-y: none;
}

B.T.W. if you want disable pinch-zoom, then use this:

/* prevent pinch-zoom for Chrome 36+, Safari 13+ */
html {
  touch-action: pan-x pan-y;
  min-height: 100%; /* prevent pinch-zoom at page bottom */
}

this:

// prevent pinch-zoom for iOS Safari 9~12
if (window.GestureEvent && !('touchAction' in document.documentElement.style)) {
  document.documentElement.addEventListener('gesturestart', (e)=>{e.preventDefault()}, {passive: false, capture:true});
}

and this:

<!-- prevent pinch-zoom for Chrome / old Safari -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
fuweichin
  • 1,398
  • 13
  • 14
0

iNoBounce works until you use a gesture with more than one finger. Let's say you pull down the web page with two fingers (for example), then you will get the refresh.

For now, the only approach that have worked for me (but it disables zoom, scroll and other touch functions) is use event.preventDefault() listening to "touchmove" with passive set to false.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 22 '21 at 19:25
  • DIdn't immediately occur for me. I'm trying to use two fingers but it's behaving as I need. – VH-NZZ Sep 23 '21 at 04:26
-1

Ths 2013 library called iNoBounce (https://github.com/lazd/iNoBounce) actually still does the trick pretty well on iOS 15.

Straightforward replication of the example in the documentation did disable the pull to refresh.

VH-NZZ
  • 5,248
  • 4
  • 31
  • 47
  • inobounce does not work for me (iPadOS 15.0.1), I tried with basic.html and when I touchmove the div I can refresh the page. However when I scroll down the lorem ipsum inside the div and then scroll back up then I can't trigger the refresh. When I tap outside the div then I can with touchmove on the div refresh the page. – Alexander Oct 04 '21 at 13:35
  • Same for me, also on IPadOs 15.0.1 – alexcodes Oct 12 '21 at 12:56