Disable pull-to-refresh in iOS 15 Safari
Asked Answered
C

7

27

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.

Clubby answered 20/9, 2021 at 21:25 Comment(3)
it looks like apple screwed us again.. preventing the document or body from scrolling does not seem possible anymore, see 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: bodyscrolllock-modal.vercel.appHazy
Have you found a solution? This makes our mobile web app so much worse now.Sacken
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.Triangulation
C
-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.

Clubby answered 22/9, 2021 at 8:16 Comment(2)
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.Overword
Same for me, also on IPadOs 15.0.1Indrawn
R
18

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;
}
Rudd answered 15/10, 2021 at 19:48 Comment(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.Chimb
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!Piegari
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?Prostitution
Perfect! This worked like a charm for my use case!!! Thanks a bunch, you saved me a lot of headache!!!Ripe
T
12

In 2022, this works nicely for me:

body {
  overflow: hidden;
}
Tarsus answered 4/10, 2022 at 0:10 Comment(0)
E
8

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

Endomorph answered 4/1, 2022 at 13:39 Comment(3)
I have added touch-action:none in the body then solved the issuePartain
blocks the scroll.....totally...........Glamorous
This didn't work for me.Gleanings
J
7

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. To disable pinch-zoom, use CSS

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

and JS

// 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 HTML

<!-- prevent pinch-zoom for Chrome / old Safari -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
Jeramyjerba answered 5/12, 2022 at 16:28 Comment(1)
Excellent! Implemented it worked for me. Thank you for taking the time to write this up.Trying
B
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.

Boldface answered 22/9, 2021 at 14:54 Comment(2)
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.Hamman
DIdn't immediately occur for me. I'm trying to use two fingers but it's behaving as I need.Clubby
L
0

I have applied:

html, body {
  overscroll-behavior: none;
}

and it resolved the problem for the main container. In case you have also some other scrollable sub-sections then apply the same overscroll behavior on that + make sure you dont have full-height set on the element.

src: https://justinharter.com/disable-safaris-pull-to-refresh-on-ipad-perfect-for-external-mouse-trackpads/

Longsufferance answered 5/7 at 11:22 Comment(0)
C
-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.

Clubby answered 22/9, 2021 at 8:16 Comment(2)
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.Overword
Same for me, also on IPadOs 15.0.1Indrawn

© 2022 - 2024 — McMap. All rights reserved.