Hybrid Apps, scrolling DIVs on Android 4.x

Viewed 759

I have done a lot of research in various forums but have not found a real solution yet. I'm creating a hybrid HTML 5 Single Page App. It's main page contains a scrolling div (id="content") with "overflow:scroll" or "overflow:auto". What I'm describing here is a destilled version of my problem, but the core point is that I really need a scrolling div, I cannot rely on the scrolling of the window itself.

I've run in many problems that have already been described here and in other forums, e.g.:

The scrolling experience is bad. The screen flickers, it is not fluid and most important: Background button-images have a kind of scroll lag or delay: the seem "stuck" while the rest of the page scrolls and after about 1/10 second, the "jump" back to the position they belong to. I was able to fix this by using the "translatez" oder "translaste3d" trick described in other posts in this forum plus setting the position of the scrolling div to absolute. But still, the scrolling is way less smooth than a native app or than scrolling the window itself.

I've tried iScroll 5 to see if it improves the scrolling experience but it faces the same problems: When the page becomes more complex with various CSS-styles it shows exactly the same flickering and stuttering as the "normal" div-scrolling. I assume that its way of using CSS "transform: translate" causes the same rendering issues.

My main problem: Setting the scroll position does not work reliably. I've tried jQuery "scrollTop()" as well as native JavaScript "element.scrollTop=...". I've also tried the workarounds described in various forums, e.g. setting the overflow of the scrolling div to "hidden", then set the scroll pos and then reset it to "auto" again. It seems to improve the situation but does not completely eleminate it. I have an extensive trace output to follow the sequence of the problem:

  • User scrolls up (momentum scrolling initiated by swipe gesture)
  • If scrollTop < 300px, I load data asnychronously and add it to the top of the content of the scrolling div
  • In order to provide the user a smooth (and not "jumpy") scroll experience I correct the scroll position by the horizontal size of the data added (i.e. scrollTop = scrollTop + horizSizeOfAddedElements), e.g. 3299px.
  • In my trace output, I can see that it works correctly: A scroll event is triggered and scrollTop returns the position I have set before
  • Only moments later, momentum scrolling seems to kick in (I have not touched the screen in the mean time, the scrolling is still going on) and resets scrollTop to where it had been before I reset it. E.g. 299px instead of 3299px.

The content has following main structure:

<!-- Navbar ----------------------------------------------------------- -->
<section id="navBarPlaceHolder">    
</section>

<!-- Content ---------------------------------------------------------- -->

<div id="contentWrapper" class="contentWrapper">
    <div id="content" class="app-container">
    </div>
</div>

Styles:

.app-container {
    padding-right: 0px;
    padding-left: 0px;
    margin-left: 0px; margin-top:0px; margin-right:0px; margin-bottom:0px;
    display:inline-block; 
    vertical-align: top;
    min-width: 320px;
    overflow-y: auto; 
    position:absolute;
    top: 45px; bottom: 12px;
    -webkit-overflow-scrolling: touch; 
 }

.app-container > * {
    -webkit-transform: translate3d(0,0,0);
    -webkit-transform: translateZ(0px);

}

.contentWrapper{
    x-border: solid; border-color:black; border-width:1px; 
    margin-left: auto; margin-right: auto;
    white-space: nowrap; 
    vertical-align: top;
    margin-left: auto; margin-right:auto;
    overflow:hidden;
    position: absolute; 
    top: 10px; bottom: 5px;
}

I have also tried other workarounds, like using "transform:translateY" instead of setting scrollTop but in this case I would have rely on every scroll event to be fired correctly in order to undo the "translateY" when no more dynamic data is added to the top of the div. But on mobile browsers, not every scroll event will be fired as expected.

Btw., the whole mechanism works fine on current desktop browsers (Chrome, IE, Firefox) as well as on the Android Google Chrome browser (installed from Google Play). Is the android stock browser really so much worse than the Google Chrome browser? So it seems that for more complex apps, one needs to resort to native apps instead of HTML 5 apps.

Any thoughts on this are highly appreciated, thanks a lot in advance Spa

0 Answers
Related