Skip to main content

Suggested edits

Approve, reject, or improve edits suggested by users.

about the Suggested edits queue.

Your daily reviews 0 /40
Review the following answer edit
18 answers
110598 views
Disabling android's chrome pull-down-to-refresh feature
Sebastiano's user avatar
Sebastiano
1,7522 gold badges13 silver badges13 bronze badges
Asked 9 years, 6 months ago
180

Edit summary: Judging from the comments, most people is coming here to find a way to manually disable pull-to-refresh on the client side. This is not possible anymore. Let's give our readers the answer they are actually looking for.

Google has made pull-to-refresh mandatory. Since Chrome version 75, you can not turn it off.

What you can do to avoid unwanted refreshes is scrolling up slowly and looking at the scroll bar so you can stop scrolling in time before hitting the top of the page.

However, you can opt your own website out of pull-to-refresh.

The default action of the pull-to-refresh effect can be effectively prevented by doing any of the following :

  1. preventDefault’ing some portion of the touch sequence, including any of the following (in order of most disruptive to least disruptive):
  • a. The entire touch stream (not ideal).
  • b. All top overscrolling touchmoves.
  • c. The first top overscrolling touchmove.
  • d. The first top overscrolling touchmove only when 1) the initial touchstart occurred when the page y scroll offset was zero and 2) the touchmove would induce top overscroll.
  1. Applying “touch-action: none” to touch-targeted elements, where appropriate, disabling default actions (including pull-to-refresh) of the touch sequence.
  2. Applying “overflow-y: hidden” to the body element, using a div for scrollable content if necessary.
  3. Disabling the effect locally via chrome://flags/#disable-pull-to-refresh-effect)Disabling the effect locally via chrome://flags/#disable-pull-to-refresh-effect). Only available in Chrome 41 to 74. Removed in Chrome 75.

See more

The default action of the pull-to-refresh effect can be effectively prevented by doing any of the following :

  1. preventDefault’ing some portion of the touch sequence, including any of the following (in order of most disruptive to least disruptive):
  • a. The entire touch stream (not ideal).
  • b. All top overscrolling touchmoves.
  • c. The first top overscrolling touchmove.
  • d. The first top overscrolling touchmove only when 1) the initial touchstart occurred when the page y scroll offset was zero and 2) the touchmove would induce top overscroll.
  1. Applying “touch-action: none” to touch-targeted elements, where appropriate, disabling default actions (including pull-to-refresh) of the touch sequence.
  2. Applying “overflow-y: hidden” to the body element, using a div for scrollable content if necessary.
  3. Disabling the effect locally via chrome://flags/#disable-pull-to-refresh-effect).

See more

Google has made pull-to-refresh mandatory. Since Chrome version 75, you can not turn it off.

What you can do to avoid unwanted refreshes is scrolling up slowly and looking at the scroll bar so you can stop scrolling in time before hitting the top of the page.

However, you can opt your own website out of pull-to-refresh.

The default action of the pull-to-refresh effect can be effectively prevented by doing any of the following :

  1. preventDefault’ing some portion of the touch sequence, including any of the following (in order of most disruptive to least disruptive):
  • a. The entire touch stream (not ideal).
  • b. All top overscrolling touchmoves.
  • c. The first top overscrolling touchmove.
  • d. The first top overscrolling touchmove only when 1) the initial touchstart occurred when the page y scroll offset was zero and 2) the touchmove would induce top overscroll.
  1. Applying “touch-action: none” to touch-targeted elements, where appropriate, disabling default actions (including pull-to-refresh) of the touch sequence.
  2. Applying “overflow-y: hidden” to the body element, using a div for scrollable content if necessary.
  3. Disabling the effect locally via chrome://flags/#disable-pull-to-refresh-effect). Only available in Chrome 41 to 74. Removed in Chrome 75.

See more

Google has made pull-to-refresh mandatory. Since Chrome version 75, you can not turn it off.
What you can do to avoid unwanted refreshes is scrolling up slowly and looking at the scroll bar so you can stop scrolling in time before hitting the top of the page.
However, you can opt your own website out of pull-to-refresh.
The default action of the pull-to-refresh effect can be effectively prevented by doing any of the following :The default action of the pull-to-refresh effect can be effectively prevented by doing any of the following :
5 identical lines skipped
2. Applying “`touch-action: none`” to touch-targeted elements, where appropriate, disabling default actions (including pull-to-refresh) of the touch sequence.2. Applying “`touch-action: none`” to touch-targeted elements, where appropriate, disabling default actions (including pull-to-refresh) of the touch sequence.
3. Applying “`overflow-y: hidden`” to the body element, using a div for scrollable content if necessary.3. Applying “`overflow-y: hidden`” to the body element, using a div for scrollable content if necessary.
4. Disabling the effect locally via `chrome://flags/#disable-pull-to-refresh-effect`).
4. <s>Disabling the effect locally via `chrome://flags/#disable-pull-to-refresh-effect`).</s> Only available in Chrome 41 to 74. Removed in Chrome 75.
[See more][1][See more][1]
2 identical lines skipped
Proposed Sep 1 at 18:06 by an anonymous user
9
  • 14
    Thank you @Evyn . I cannot believe this was a quick fix! I set the CSS for the body element to overflow-y:hidden.Commented Mar 29, 2015 at 19:48
  • 2
    how is "chrome://flags (disable-pull-to-refresh-effect)" done programmatically ?Commented Jun 22, 2015 at 21:49
  • 2
    @SomeoneSomewhere as far as I know, its not impossible. chrome settings can only be set by the user - it would pose a security risk otherwise
    – Mike
    Commented May 11, 2016 at 11:34
  • 2
    Applying “overflow-y: hidden” to the body element, using a div for scrollable content worked for me.
    – Robin
    Commented Nov 13, 2017 at 8:09
  • 1
    Option 3 is just awesome, tried dozens of options and finally the most simple option works, thanks a lot!Commented Mar 8, 2018 at 17:31
160

I've created a small HTML5 web application for my company.

This application displays a list of items and everything works fine.

The application is mainly used on android phones and Chrome as browser. Also, the site is saved on the home screen so Android manage the whole thing as an app (using a WebView I guess).

Chrome Beta (and I think also the Android System WebView) has introduced a "pull down to refresh" feature (See this link for example).

This is an handy feature but I was wondering if it can be disabled with some meta tag (or javascript stuff) because the refresh can be easily triggered by the user while navigating the list and the whole app is reloaded.

Also this is a feature not needed by the application.

I know that this feature is still available only in Chrome beta, but I have the sensation that this is landing on the stable app, too.

Thank you!

Edit: I've uninstalled Chrome Beta and the link pinned to the home screen now opens with the stable Chrome. So the pinned links starts with Chrome and not with a webview.

Edit: today (2015-03-19) the pull-down-to-refresh has come to the stable chrome.

Edit: from @Evyn answer I follow this link and got this javascript/jquery code that work.

As @bcintegrity pointed out, I hope for a site manifest solution (and/or a meta-tag) in the future.

Moreover suggestions for the code above are welcome.

CC BY-SA 3.0
7
  • 29
    Yeah this really sucks. Was in middle of form and scrolled to top too far and it refreshed and lost everything. This is a retarded default feature, I click the Refresh icon if I want to refresh!Commented Mar 24, 2015 at 22:11
  • 12
    Would be nice if this feature could be disabled in my web app manifest. Unfortunately, every page on my web app has scrollable content, making it almost impossible to navigate without refreshing. I'm a little ticked. :/Commented Mar 27, 2015 at 22:33
  • This is good info. I hate web sites that disable the pull to refresh feature. I'd like to develop a feature to make the refresh work regardless of page content.Commented Apr 24, 2016 at 12:41
  • 8
    Speaking as a web developer, pulldown refresh is incompatible with data-driven websites, as it reloads the application. It makes it impossible for a user to scroll to the top of a page without refreshing the whole page. I am 100% supportive of Chrome, hope they remove this anti-feature.
    – Beans
    Commented Jun 9, 2016 at 23:57
  • 5
    I faced myself with this GC "feature"... plenty web pages, many forms, one careless pull down with my finger and data on this page are lost! Retard function IMO. It should be off by default, who need it then let code it. I wondered by days why my "clients" occasionally lost their data on GC...
    – Ludus H
    Commented Dec 23, 2017 at 10:54
158

Chrome 75 and newer

Google has made pull-to-refresh mandatory with the update to version 75. You can not turn it off.

You can prevent accidental refreshes by scrolling up slowly.

If you own a website, you can still opt your website out of pull-to-refresh using the following CSS property.

Simple solution for 2019+ for site owners

Chrome 63 has added the overscroll-behaviour css property to help out with exactly this. Have a read through this guide by Google to get a good idea of how you can handle it.

Here is their TL:DR

The CSS overscroll-behavior property allows developers to override the browser's default overflow scroll behavior when reaching the top/bottom of content. Use cases include disabling the pull-to-refresh feature on mobile, removing overscroll glow and rubberbanding effects, and preventing page content from scrolling when it's beneath a modal/overlay.

To get it working, all you have to add is this in your website's CSS:

body {
  overscroll-behavior: contain;
}

It is also only supported by Chrome, Edge and Firefox for now but I'm sure Safari will add it soon as they seem to be fully onboard with service workers and the future of PWA's.

Solution for Chrome 41 to 74

Open chrome://flags, search for disable-pull-to-refresh-effect, and tap on "Disable".

6
  • 19
    this is the most up to date anwser
    – colxi
    Commented Mar 9, 2018 at 21:20
  • Has anyone else noticed this delaying the appearance of the "Add to Homescreen" chrome banner?Commented Jul 1, 2018 at 22:28
  • 6
    had to apply it to the html element in order to disable itCommented Sep 11, 2018 at 11:31
  • 1
    This work only for Android , Chrome on IOs still to show glows effect + native pull to refresh
    – Fky
    Commented Feb 8, 2019 at 8:56
  • developers.google.com/web/updates/2017/11/overscroll-behavior this link can also explain better
    – Arun-G
    Commented Nov 29, 2019 at 7:05
14

At the moment you can only disable this feature via chrome://flags/#disable-pull-to-refresh-effect - open directly from your device.

You could try to catch touchmove events, but chances are very slim to achieve an acceptable result.

3
  • 1
    Thank you Kevin for the answer .I could not accept this as the accepted one because I was looking for something not dependent from the users. However this method works, so I'll upvote your answer as I gain enough reputation.Commented Mar 24, 2015 at 9:37
  • It's a pity this seems to be the best solution - what if that flag setting changes in the future, or you want to be able to use pull to refresh on other sites...Surprised that this can't be controlled programmatically. :(.Commented Sep 18, 2017 at 5:42
  • 1
    If the CEO of Google is reading this, please remove this feature. It does not seem that it can be easily and comprehensively disabled, and in my opinion is a web application "feature" that not all web applications want.Commented Oct 9, 2017 at 4:22
9

After many hours of trying, this solution works for me

$("html").css({
    "touch-action": "pan-down"
});
2
  • There is no need to use jQuery for this. Just add the "touch-action: pan-down" to your css code file.Commented Feb 12, 2018 at 22:15
  • 1
    just use this in your css: html{touch-action:pan-down}Commented Mar 7, 2019 at 13:28
8

I use MooTools, and I have created a Class to disable refresh on a targeted element, but the crux of it is (native JS):

var target = window; // this can be any scrollable element
var last_y = 0;
target.addEventListener('touchmove', function(e){
    var scrolly = target.pageYOffset || target.scrollTop || 0;
    var direction = e.changedTouches[0].pageY > last_y ? 1 : -1;
    if(direction>0 && scrolly===0){
        e.preventDefault();
    }
    last_y = e.changedTouches[0].pageY;
});

All we do here is find the y direction of the touchmove, and if we are moving down the screen and the target scroll is 0, we stop the event. Thus, no refresh.

This means we are firing on every 'move', which can be expensive, but is the best solution I have found so far ...

1
  • 2
    It's safe to stop watching as soon as the user scrolls down, as the pull to refresh has no chance of being triggered. Likewise, if scrolltop > 0, the event won't be triggered. In my implementation, I bind the touchmove event on touchstart, only if scrollTop <= 0. I unbind it as soon as the user scrolls down (initialY >= e.touches[0].clientY). If the user scrolls up (previousY < e.touches[0].clientY), then I call preventDefault.
    – nicbou
    Commented Aug 7, 2015 at 12:13
8

You can try this

body {
  /* Disables pull-to-refresh but allows overscroll glow effects. */
  overscroll-behavior-y: contain;
}

example :

https://ebidel.github.io/demos/chatbox.html

full doc https://developers.google.com/web/updates/2017/11/overscroll-behavior

1
  • The correct answer 👍
    – uxcxdx
    Commented May 23, 2022 at 5:59
4

AngularJS

I have successfully disabled it with this AngularJS directive:

//Prevents "pull to reload" behaviour in Chrome. Assign to child scrollable elements.
angular.module('hereApp.directive').directive('noPullToReload', function() {
    'use strict';

    return {
        link: function(scope, element) {
            var initialY = null,
                previousY = null,
                bindScrollEvent = function(e){
                    previousY = initialY = e.touches[0].clientY;

                    // Pull to reload won't be activated if the element is not initially at scrollTop === 0
                    if(element[0].scrollTop <= 0){
                        element.on("touchmove", blockScroll);
                    }
                },
                blockScroll = function(e){
                    if(previousY && previousY < e.touches[0].clientY){ //Scrolling up
                        e.preventDefault();
                    }
                    else if(initialY >= e.touches[0].clientY){ //Scrolling down
                        //As soon as you scroll down, there is no risk of pulling to reload
                        element.off("touchmove", blockScroll);
                    }
                    previousY = e.touches[0].clientY;
                },
                unbindScrollEvent = function(e){
                    element.off("touchmove", blockScroll);
                };
            element.on("touchstart", bindScrollEvent);
            element.on("touchend", unbindScrollEvent);
        }
    };
});

It's safe to stop watching as soon as the user scrolls down, as the pull to refresh has no chance of being triggered.

Likewise, if scrolltop > 0, the event won't be triggered. In my implementation, I bind the touchmove event on touchstart, only if scrollTop <= 0. I unbind it as soon as the user scrolls down (initialY >= e.touches[0].clientY). If the user scrolls up (previousY < e.touches[0].clientY), then I call preventDefault().

This saves us from watching scroll events needlessly, yet blocks overscrolling.

jQuery

If you are using jQuery, this is the untested equivalent. element is a jQuery element:

var initialY = null,
    previousY = null,
    bindScrollEvent = function(e){
        previousY = initialY = e.touches[0].clientY;

        // Pull to reload won't be activated if the element is not initially at scrollTop === 0
        if(element[0].scrollTop <= 0){
            element.on("touchmove", blockScroll);
        }
    },
    blockScroll = function(e){
        if(previousY && previousY < e.touches[0].clientY){ //Scrolling up
            e.preventDefault();
        }
        else if(initialY >= e.touches[0].clientY){ //Scrolling down
            //As soon as you scroll down, there is no risk of pulling to reload
            element.off("touchmove");
        }
        previousY = e.touches[0].clientY;
    },
    unbindScrollEvent = function(e){
        element.off("touchmove");
    };
element.on("touchstart", bindScrollEvent);
element.on("touchend", unbindScrollEvent);

Naturally, the same can also be achieved with pure JS.

3
  • I had to use e.originalEvent.touches[0].clientY to make this work. Still struggling with the logic when to prevent reload. Right now it seems to randomly prevent scrolling up ... Put thanks for the hint in the right direction!
    – thomas
    Commented Nov 6, 2015 at 16:06
  • What element is the directive added to?
    – Fizzix
    Commented Feb 10, 2016 at 22:37
  • The AngularJS directive worked well for me. We are using Framework7 and Angular together (wouldn't suggest it) and something was blocking the correct behaviour of scrollTop. So I had to modify when the blockScroll would be added to the element. But just wanted to say thanks!Commented Jun 1, 2016 at 22:16
4

Simple Javascript

I implemented using standard javascript. Simple and easy to implement. Just paste and it works fine.

<script type="text/javascript">         //<![CDATA[
     window.addEventListener('load', function() {
          var maybePreventPullToRefresh = false;
          var lastTouchY = 0;
          var touchstartHandler = function(e) {
            if (e.touches.length != 1) return;
            lastTouchY = e.touches[0].clientY;
            // Pull-to-refresh will only trigger if the scroll begins when the
            // document's Y offset is zero.
            maybePreventPullToRefresh =
                window.pageYOffset == 0;
          }

          var touchmoveHandler = function(e) {
            var touchY = e.touches[0].clientY;
            var touchYDelta = touchY - lastTouchY;
            lastTouchY = touchY;

            if (maybePreventPullToRefresh) {
              // To suppress pull-to-refresh it is sufficient to preventDefault the
              // first overscrolling touchmove.
              maybePreventPullToRefresh = false;
              if (touchYDelta > 0) {
                e.preventDefault();
                return;
              }
            }
          }

          document.addEventListener('touchstart', touchstartHandler, false);
          document.addEventListener('touchmove', touchmoveHandler, false);      });
            //]]>    </script>
4
  • This worked very well for Chrome, but caused some issues with scrolling up for me on Safari/iOS 9.2 when scrolling a div at the top of the page (reproduced here). I ended up using the body: {overflow-y:hidden} trick from Evyn above.
    – sennett
    Commented Mar 7, 2016 at 10:52
  • downvoting as does not works on chrome , but works in firefox example , embed.plnkr.co/rqbOVSOkKyhAgoHK2sEP open in MOBILE ONLY
    – vijay
    Commented Feb 14, 2017 at 13:02
  • the link that you pasted did work in chrome as well on my android mobile. it did not allow to refresh on pull. which version of android/ios are you using to test?Commented Feb 16, 2017 at 23:05
  • 2
    From Chrome 56 you need to set passive: false to make it work: document.addEventListener('touchstart', touchstartHandler, { passive: false }); document.addEventListener('touchmove', touchmoveHandler, { passive: false });Commented Oct 27, 2017 at 1:49
4

The best solution on pure CSS:

body {
    width: 100%;
    height: 100%;
    display: block;
    position: absolute;
    top: -1px;
    z-index: 1;
    margin: 0;
    padding: 0;
    overflow-y: hidden;
}
#pseudobody {
    width:100%;
    height: 100%;
    position: absolute;
    top:0;
    z-index: 2;
    margin: 0;
    padding:0;
    overflow-y: auto;
}

See this demo: https://jsbin.com/pokusideha/quiet

1
  • do you really tested this on a mobile using chrome?Commented Mar 22, 2019 at 13:31
3

I find setting your body CSS overflow-y:hidden is the simplest way. If you did want to have a scrolling application page you can just use a div container with scrolling features.

1
  • Seems impossible to fix it with a line but works like a charm, thanks a lot!Commented Mar 8, 2018 at 17:31
2

Note that overflow-y is not inherited, so you need to set it on ALL block elements.

You can do this with jQuery simply by:

        $(document.body).css('overflow-y', 'hidden'); 
        $('*').filter(function(index) {
            return $(this).css('display') == 'block';
        }).css('overflow-y', 'hidden');
1
  • Among the other answers, this one really helps. Thanks. Add this line into css. body{ overflow-y: hidden; }Commented Feb 22, 2017 at 8:56
2

Since a couple of weeks I found out that the javascript function that I used to disable the Chrome refresh action won't work anymore. I have made this to solve it:

$(window).scroll(function() {
   if ($(document).scrollTop() >= 1) {
      $("html").css({
         "touch-action": "auto"}
      );
   } else {
      $("html").css({
         "touch-action": "pan-down"
      });
   }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

    1

    Pure js solution.

    // Prevent pull refresh chrome
        var lastTouchY = 0;
        var preventPullToRefresh = false;
        window.document.body.addEventListener("touchstart", function(e){
            if (e.touches.length != 1) { return; }
            lastTouchY = e.touches[0].clientY;
            preventPullToRefresh = window.pageYOffset == 0;
        }, false);
    
        window.document.body.addEventListener("touchmove", function(e){
    
            var touchY = e.touches[0].clientY;
            var touchYDelta = touchY - lastTouchY;
            lastTouchY = touchY;
            if (preventPullToRefresh) {
                // To suppress pull-to-refresh it is sufficient to preventDefault the first overscrolling touchmove.
                preventPullToRefresh = false;
                if (touchYDelta > 0) {
                    e.preventDefault();
                    return;
                }
            }
    
        }, false);
    
      1

      I solved the pull-down-to-refresh problem with this:

      html, body {
          width: 100%;
          height: 100%;
          overflow: hidden;
      }
      
        1

        The simple and recommended solution in 2023, as per the recommendations by Google and Mozilla, which works in both mobile browsers:

        HTML {
            overscroll-behavior: none;
        }
        BODY {
            overscroll-behavior-y: contain;
        }
        
          0

          What I did was add following to the touchstart and touchend/touchcancel events:

          scrollTo(0, 1)
          

          Since chrome does not scroll if it's not on scrollY position 0 this will prevent chrome from doing pull to refresh.

          If it still does not work, try also doing that when the page loads.

            0

            This worked for me:

            html {
              overscroll-behavior-y: contain;
            }
            
              0

              This is what I did using nextjs/react

              useEffect(() => {
                
                  function preventPullToRefresh() {
                   var lastTouchY = 0;
                   document.addEventListener(
                    "touchstart",
                    function (e) {
                     if (e.touches.length !== 1) return;
                     lastTouchY = e.touches[0].clientY;
                    },
                    {passive: false}
                   );
              
                   document.addEventListener(
                    "touchmove",
                    function (e) {
                     var touchY = e.touches[0].clientY;
                     var touchYDelta = touchY - lastTouchY;
                     lastTouchY = touchY;
                     if (touchYDelta > 0) {
                      e.preventDefault();
                      return;
                     }
                    },
                    {passive: false}
                   );
                  }
              
                  preventPullToRefresh();
                }, []);