5

I'm currently developing a mobile websiteon which I use jQuery Mobile. When switching pages I use the slide transition. Because these pages are quite long scrolling is needed.

When scrolled down and clicking on a link there is a visible jump when the page is scrolled to the top before sliding in the new page. As the two pages sit side-by-side when transitioning scrolling to the top is needed at some point.

One thing I've tried is this: I can offset the new page from the top so that it begins at the level the page is scrolled to and reset the offset back to 0 when the animation is complete, but then the page will remain scrolled down. If I use window.scrollTo or jQuery's scrollTop() there is a noticeable flicker most noticeable with the fixed header.

Is there any other thing I can do which keeps the old page scrolled but the new page unscrolled?

I've tested this in an iPod touch 3rd gen, iPhone 4 and iPhone 4s, and surprisingly the device which has given me the least amount of flicker so far has been the iPod touch.

D A
  • 413
  • 1
  • 4
  • 10

3 Answers3

0

Simply add this CSS

div[data-role='page'] { bottom: 0; -webkit-overflow-scrolling: touch; }

(from here)

Community
  • 1
  • 1
Aximili
  • 28,626
  • 56
  • 157
  • 216
0

I am answering this question because it is the original one posted about this topic, and states clearly that the issue here is a noticeable flicker by using window.scrollTo(), jQuery's scrollTop() or the controversial $.mobile.silentScroll() from the JQM library (timeout + scroll).

I have had recently to address exactly the same issue, and that is what I came up: the great JQM team has done a great job in the past to optimize and speed-up transitions also for low-end mobile devices.

In short, this critical point has been solved by JQM in some way by trying to pair the pages to a certain value inside the ยง.mobile.silentScroll() function. I had to remove this function to build my own:

$(document).on("mobileinit", function () {
  // other settings...
  $.mobile.SerialTransition.prototype.scrollPage = $.noop;
  $.mobile.ConcurrentTransition.prototype.scrollPage = $.noop;
});

As I have two kind of pages, the first one where I need to remember the scroll position (list page), and a second one (card page) where I need to start always from the top, I will store this information inside a custom data-attribute.

Here is for instance this setting for the three pages in my example below:

<div id="page-one" data-role="page" data-transition-scroll="keep-position">
<div id="page-two" data-role="page" data-transition-scroll="top-position">
<div id="page-three" data-role="page" data-transition-scroll="keep-position">

As pointed out in the question, I have had also to offset the page from the top, and this is the whole code:

var scrollHandler = {
  setScrollData: function (prevPage, toPage) { 
    if(typeof toPage == "object" && typeof prevPage == "object") {
      $(prevPage).data("scroll-top", $(window).scrollTop());
    }
  },
  resetContent: function (toPage) {
    var scrollMode = $(toPage).data("transition-scroll");
    if(scrollMode === "top-position") {
      var content = $(toPage).find(".ui-content")[0];
      var contentStyle = $(content).attr("style"); /* Force reflow */
        $(content).css({"top": "0px"});
    }
  },
  freezeContent: function (prevPage) {
    var scrollTop = $(prevPage).data("scroll-top"),
        content = $(prevPage).find(".ui-content")[0],
        fixedHeader = $(prevPage).find(".ui-header-fixed")[0],
        headerBottom = $(fixedHeader).outerHeight() - fixedHeader.offsetTop;
    $(content).css({"top": -scrollTop + "px"});
    window.scrollTo(0,0);
  },
  unFreezeContent: function (toPage) {
    var scrollTop = $(toPage).data("scroll-top"),
        scrollMode = $(toPage).data("transition-scroll"),
        content = $(toPage).find(".ui-content")[0],
        contentStyle = $(content).attr("style"); /* Force reflow */
    $(content).removeAttr("style");
    window.scrollTo(0, scrollMode ==="top-position" ? 0 : scrollTop);
  }
};

The JQM pageevents used here are are the following:

$(document).on("pagecontainerbeforehide", function(e, ui) { 
  scrollHandler.freezeContent(ui.prevPage);
});

$(document).on("pagecontainerbeforechange", function(e, ui) { 
  scrollHandler.setScrollData(ui.prevPage, ui.toPage);
});

$(document).on("pagecontainerbeforeshow", function(e, ui) { 
  scrollHandler.resetContent(ui.toPage);
});

$(document).on("pagecontainershow", function(e, ui) { 
  scrollHandler.unFreezeContent(ui.toPage);
});

Lastly, there is also a little bit of CSS:

/* large desktop screen */
.ui-header,
.ui-content,
.ui-footer {
  max-width: 870px;
  margin: auto;
}
/* needed for the scrollhandler */
.ui-content {
  position: relative; 
  width: 100%;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

Additional note

For external pages and for pages which aren't dom-cached, there would be the need for a custom page history because:

  1. in my example the scroll value is stored inside the page itself and
  2. the current standard JQM page history implementation it would not be enough for this purpose

Here is an example:

The slide transition was slowed down on purpose to examine the result:

transition animation

deblocker
  • 7,629
  • 2
  • 24
  • 59
-1

just put return false; at the end of the javascript function that is called.

     function yourFunctionBeingCalled(){
       /*your code*/
       return false;
     }

you can also use preventDefault(); or event.stopPropagation(); functions

reffer: event.preventDefault() vs. return false

Hope it helped.

Community
  • 1
  • 1
Aravind
  • 320
  • 2
  • 10