0

I'm adding a back to top button fixed to bottom of the browser window. When clicked, it scrolls to top in desktop and Android, but not iPhone. On the iPhone, the scrollTo event reveals the address bar and the bottom mobile button bar, but does not return the user to the top of the page.

EDIT: The address bar and button bar on the iPhone appears when a touch event occurs within 20-30px of the bottom of the screen. This is why this back to top button doesn't work. Moving it 40px up stops the address/button bars from appearing.

I've attempted to just place it raw:

$('#scroll-to-top-button').on('click', function() {
    window.scrollTo(0,0);
});

And with a timer:

$('#scroll-to-top-button').on('click', function() {
    window.setTimeout(function() {
        window.scrollTo(0,0);
    }, 500);
});

I tried using scrollTop, which had the same results: browser button bar and address bar appear, but no scroll.

I also tried initiating the scrollTo and at the same time setting a timeOut with another scrollTo. The timeout never fires.

I did also try scrolling html or body, or a combination of the two:

$('#scroll-to-top-button').on('click', function() {
    $('html,body').animate({
        scrollTop: 0,
    }, 200);
});

Only html

$('#scroll-to-top-button').on('click', function() {
    $('body').animate({
        scrollTop: 0,
    }, 200);
});

only body

$('#scroll-to-top-button').on('click', function() {
    $('html').animate({
        scrollTop: 0,
    }, 200);
});

I've tried resetting the button to an anchor tag and trying to get it to link within the page. This doesn't work with just basic html anchor functionality:

<div id="main-body"> ... lots of content forcing scrollbars to appear ... </div>

<a id="scroll-to-top-button" class="btn btn-default" href="#main-body">Back to Top</a>

And tried preventing default and animating the link to the anchor:

$('#scroll-to-top-button').on('click', function(e) {
    e.preventDefault();
    $('html,body').animate({
        scrollTop: 0,
    }, 200);
});

Here's a link demonstrating the problem. In this link, the code is using one of my last examples down this question, where it's purely an anchor tag trying to link to top of page.

http://willanni.com/dev/iphone-scroll/

I thought maybe missing the viewport tag might be causing it, so I added the following: <meta name="viewport" content="width=device-width, initial-scale=1">. However. When I add that in, it still does not make it work.

Besides forcing the address bar and button bar to always be visible in iPhone, is there a way to get this to scroll to top of window in iPhone? (Note: iPad doesn't have this issue, though it had a different weird issue that required the timeout to fix. Different story though)

Will Lanni
  • 923
  • 12
  • 25
  • Instead of scrolling `window`, try `html` and/or `body`. – evolutionxbox Apr 13 '16 at 20:47
  • @evolutionbox nope, doesn't work. I should have mentioned I tried that. I'll update question. – Will Lanni Apr 13 '16 at 21:45
  • Can you post a link showing the problem? – theCodeSurgeon Apr 13 '16 at 22:40
  • @theCodeSurgeon added a link into the page. As I note, that code is just an tag trying to jump to an anchor at the top of the page. – Will Lanni Apr 13 '16 at 22:56
  • OK, just figured out that the address and button bars appear when a user touches within about 20-30px of the bottom of the screen in iPhone. So... I may need to restructure this question to how to have a button at bottom of screen that doesn't trigger that event. – Will Lanni Apr 13 '16 at 23:15
  • Have you tried this? http://stackoverflow.com/questions/3705937/document-click-not-working-correctly-on-iphone-jquery - seems stupid but cursor:pointer saved my life a couples of times, in similar cases. – theCodeSurgeon Apr 13 '16 at 23:16
  • @theCodeSurgeon the issue is the position of the button fixed to the bottom of the screen. When the browser bar/button bar are hidden, tapping anywhere within approximately 30px from bottom of the screen forces them to appear, and cancels all other javascript functions (that I've tried so far). I'm attempting to capture touch events down there to see if I can prevent them, we'll see how it goes... – Will Lanni Apr 13 '16 at 23:40

2 Answers2

0

Try using jQuery animate on body and html:

$("BODY,HTML").animate({
    scrollTop: 0
}, 100); 
// second parameter is time so adjust it if you please
theCodeSurgeon
  • 460
  • 2
  • 9
  • 1
    Or use velocity.js - also html elements don't need to be capitalised. – evolutionxbox Apr 13 '16 at 20:59
  • Nope, I should have mentioned I tried that before, and it didn't work. The animate also merely pushes the button bar and address bar visible. I have to tap a second time to get it to work. – Will Lanni Apr 13 '16 at 21:55
0

The answer is that there really is no way to do this without forcing the address/buttons bar to be always visible.

The iPhone captures any touch event within about 20-30px of the bottom of the screen, and displays the address and bottom buttons bar. No page script, button, or links are triggered or registered as touched until the bar is revealed. A position: fixed, bottom: 0; button then is not able to be activated until the second touch:

  1. First touch reveals the bottom button bar (and address bar)
  2. Second touch activates whatever button/script/anchor functionality is in place

Adding an event listener to the window doesn't capture a touch event in that area of the screen while the button bar is hidden. For example, in order to test I set a timeout to allow myself a bit of time to scroll down and hide the bottom bar. In all areas of the screen except the bottom, this worked:

window.addEventListener('touchstart', function() {
    setTimeout(function() {
        alert('touchstart');
    }, 500);
});

In that bottom region, nothing.

So, in effect, to have a button attached to the bottom of the screen work on first click, you'll need to apply some hacky css to the body and html tags to force the address and button bars to always appear:

html,body {
    -webkit-overflow-scrolling: touch !important;
    overflow: auto !important;
    height: 100% !important;
}
Will Lanni
  • 923
  • 12
  • 25