0

I have been working on a jQuery Mobile site and have been noticing that once the page was loaded it would jump back to the top of the page after a second or two - giving a horrible user experience if the user had scrolled down immediately.

It turns out this only happens when an HTML 5 VIDEO tag is present on the page - even if it has no associated script, absolute size and even if it's in an iframe.

I made a sample test page to demonstrate:

HOW TO TEST BEHAVIOR

  • Open the jsfiddle http://jsfiddle.net/MR966/1
  • Click Run
  • Click within the output panel IMMEDIATELY and hit space bar a couple times to scroll down. You must do this the instant the page loads.
  • After the Youtube Video has loaded the page will jump to the top.
  • Click Run and try again if you weren't fast enough.

<HEAD>

<link rel="stylesheet" href="//code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.css" />    
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.js"

<BODY>

    <h1>JQuery Mobile Video Jump</h1>

    <div class="fake-content"></div>
    <div class="fake-content"></div>
    <div class="fake-content"></div>
    <div class="fake-content"></div>
    <div class="fake-content"></div>
    <div class="fake-content"></div>
    <div class="fake-content"></div>

    <iframe width="640" height="390" src="//www.youtube.com/embed/EQ1HKCYJM5U" frameborder="0" allowfullscreen></iframe>

The content can be anything - just long enough to be at least one screen length in height.

.fake-content
{
    margin: 1em;
    background: orange;
    height: 10em;
}

NOTES

  • Removing jQuery Mobile stops this behavior : http://jsfiddle.net/MR966/2/ (you'll see the background is yellow showing it wasn't initialized). So it is definitely doing something to cause this.
  • Removing the video stops this behavior.
  • This happens for pure video tags, and YouTube - which is somewhat surprising considering they're within an externally loaded iFrame.
  • The word 'video' doesn't appear once in the jQuery Mobile sourcecode!
  • This happens on Chrome / iPad / IE / Firefox.
  • On an iPad it's particularly bad because the page doesn't jump to the top until the scrolling has completely stopped due to de-acceleration.
  • If you don't see the issue keep trying, use a slower internet connection or copy out the HTML from the JSFiddle to a local page.
  • On my actual page with other resources this is a much bigger issue than on this simple quick-fire test page.

I have video on each of my pages and if I can't fix this I'll need to abandon JQM at the eleventh hour :-/

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
  • JQM scrolls to top after it's fully loaded. If you remove the video, the behaviour won't change. Check this answer to override scroll http://stackoverflow.com/a/21989837/1771795 – Omar Jun 01 '14 at 08:31
  • but this jumping problem ironically ONLY happens on the initial page load. it's due to a $window.load related to trying to hide an iOS toolbar. I managed to disable it and added an answer below – Simon_Weaver Jun 01 '14 at 19:45

2 Answers2

2

This is normal end expected behavior, let me explain why.

When page content is larger then available page height jQuery Mobile will scroll page to the top before transitioning to the other page. This is happening because, if you transition page which is fully scrolled and second page is not high enough you will be faced with empty screen. So jQuery Mobile need to correct current viewable position before transition can occur.

This is easily solvable with iScroll plugin + iScrollView extension for jQuery Mobile. You want feel any different and everything will work just fine.

This is because height of iScroll div container is as high as screen height while inner div is scrollable and can take as much height as you need. Because top most div is high as available screen height page will normally transition without unnecessary jumping.

Read more about this problem here and here.

Community
  • 1
  • 1
Gajotres
  • 57,309
  • 16
  • 102
  • 130
  • thanks for your answer. on further investigation I believe there is a bug in the `hideUrlBar` code. The jump is triggered by code that is run when `hideUrlBar=true` but setting it to `false` breaks normal tranitions. I've detailed it in my own answer. I don't want to mess with scrollbar plugins to fix this – Simon_Weaver Jun 01 '14 at 19:28
  • it's also important to note that I only have this problem on initial page load. I'm not talking about transitions, nor do I actually have this problem on a transition - even if the destination page is very complex – Simon_Weaver Jun 01 '14 at 19:50
0

This problem only occurs on the initial page load. Looking at the source code it turns out to be related to this line:

// window load event
// hide iOS browser chrome on load if hideUrlBar is true this is as fall back incase we were too early before
if ($.mobile.hideUrlBar)
{
    $window.load( $.mobile.silentScroll );
}

I commented out just the $window.load line and the problem went away.

The problem of course is that $window.load with lots of video / images can take 1-2 seconds. So if the user scrolls in the meantime you get a painful jump.

This hideUrlBar behavior is related to trying to hide some iOS specific toolbars, that I don't even care about anyway. So I can do without this 'fall back'.

The problem with just setting hideUrlBar=false in mobileinit is that this variable is used elsewhere during normal scrolling and means the window doesn't scroll to the top after a transition. I think this is a bug.

Final fix

I settled on this:

  • In my mobileinit event I set hideUrlBar=false to prevent the $window.load event from running.
  • When the page is loaded then I re-enable it so as not to break transitions between pages (from a link at the bottom to another page).

        // mobile init
        $(document).on('mobileinit', function ()
        {
            $.mobile.hideUrlBar = false;
            $.mobile.defaultDialogTransition = "pop";
            $.mobile.defaultPageTransition = "none";
        });
    
    
        $(window).load(function ()
        {
            $.mobile.hideUrlBar = true;
        });
    

This seems to be working fine, but the fact that setting hideUrlBar=false breaks other scrolling is bad. At least I managed to fix it without having to change the source.

Misc notes

  • I ONLY had this 'jumping' problem during in initial page load. This isn't a problem for me during transitions since the $window.load code above is only ever executed once and not after a transition.

  • I have transitions turned off anyway.

  • My application is fully responsive and meant to work on mobile and desktop alike.

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689