The Official Ionic Blog

Build amazing native and progressive web apps with HTML5

nativescroll-header

intro-once upon a time, the Web Wizard was befuddled. “How can I add scroll-based features without scrolling events?” he muddled. Try as he might, he couldn’t get fake events right, so he called his advisors together for a huddle.

“Scrolling’s complicated,” he stated. “The reasons to avoid JS scrolling have faded.” So JS scrolling was enabled, and the features it allowed were fabled. It appeared JS scrolling was underrated.

Javascript scrolling had saved the day, and it lifted Ionic above the fray. But as the project quickly grew, its developers truly knew the reasons for JS scrolling would fall away.

As iOS and Android matured, native scrolling events were assured. “The time has come,” the Web Wizard said, “for native scrolling now to spread. A new functionality must be procured.”

Pull to Refresh; List Reordering; Infinite Scroll: All were configured to meet this goal. Even the $ionicScrollDelegate was carefully made to relegate itself to optional native scroll view control.

Once these changes were complete, there appeared a problem with collection-repeat. After conducting an investigation, the necessary changes caused frustration; they totaled JS scrolling nearly complete.

The solution that was committed was for JS scrolling to be permitted. Collection repeat would trigger Javascript scrolling to rigor, and native scrolling would be acquitted.

It is now my privilege to announce native scrolling’s time to pounce. For the devices that support it, you no longer must port it. Yes, it even has that native bounce!

The Real Story

Ionic was created in the fall of 2013, which by all accounts is just year and a half ago. But in mobile web time, it was a generation ago! Back then, iOS 6 still had dominant market share, and Android 2.3 demanded support.

Among other things, those browsers lacked proper scroll events. This meant that to pull off features like pull to refresh and infinite scrolling, JS scrolling would be required. Once we added it, we found we were also able to do things like list reordering and even collection-repeat.

Javascript scrolling has worked very well for Ionic, enabling us to do things that were simply impossible without it. It does use up a significant amount of processor time, though, and it requires that a lot of native functionality around touch events and input element behavior be reworked. In some ways, it’s been both a blessing and a curse.

However, Android 4.1+ supports native scroll events, and now with Lollipop and chromium webviews, those scroll events are asynchronous and won’t interrupt the smooth display of scrolling behavior. It’s an exciting time for scroll events in Android!

On the other hand, iOS is a bit of a different story. With iOS 8, Apple introduced WkWebView, which includes native scroll events. The one problem, though, is in iOS 8 Beta 3, WkWebView’s support for the file protocol broke and was never fixed. That meant that Cordova was stuck using the UIWebView that had been mostly unchanged since iOS 7, which lacked complete native scroll events.

One popular solution is to bind to touchmove events and create fake scroll events. This works nicely, until the user lets go, and iOS’s inertia scrolling takes over. We were able to accurately recreate Apple’s inertia formula but unable to get a consistently accurate read of the velocity that that equation depends on, because that’s determined in native land. We’re only provided occasional touchmove events to guess. Turns out 18ms is a long time when it comes to determining accurate velocity, and our best tests still had a 30% margin of error.

This means that iOS, for the time being, still requires JS scrolling. Android, however, gets to enjoy Ionic’s new native scrolling support. Pull to Refresh, Infinite Scrolling, List Reordering, and the $ionicScrollDelegate all work with native scrolling now!

One important caveat is that because of how collection-repeat works, it requires rapidly shifting the scroll content, hijacking the scroll behavior, and recreating the scrollbar. That’s pretty much JS scrolling, so we set it so that collection-repeat will force an ion-content to use JS scrolling.

Native scrolling can be enabled using overflow-scroll=”true” on your ion-content or using the $ionicConfigProvider to set it globally in current versions of Ionic. We want to let it be a bit more battle tested before making it the default in Android, but give it a shot in the current nightly and let us know how it’s working for you!

  • Alex GoodBoy

    Hi Perry,
    Since what release of ionic is this available ? Is is available since RC5 ? or within last night release (from 11/05/2015) ?
    Thx for this great work 😉

    • http://julienrenaux.fr/ Julien Renaux
      • http://julienrenaux.fr/ Julien Renaux

        Actually it is available on Rc5 but do not works well

        • Alex GoodBoy

          Ok, I had RC5. I’ll give a shot on nighlt releases 😉

    • Perry Govier

      It’s been a work in progress for a long time. Most of it is in RC5, and even earlier RCs, but there’s some important fixes yet in the nightlies.

  • Victor

    This post is awesome.
    If Ionic is not awesome enough, these kinds of (small) things make it even better.

    Great job!

  • Badru

    Thanks

  • Harish AS

    correct me if my understanding is wrong,if we use collection-repeat (android)we will still use old js scrolling which is laggy and non smooth?

    • Mike Hartington

      js-scrolling with collection repeat is much smoother. It has the added benefit of only having to scroll 20 items so we can have a much smoother scrolling experience.

      • Harish AS

        cool.let me check it out man.thanks

      • Darryl D

        Not really seeing any improvement, any chance of it getting better?

  • Manish Prakash

    I setup the latest version of ionic 1.0 and did

    $ionicConfigProvider.platform.android.scrolling.jsScrolling(false); so as to enable native scrolling on android.

    But when i run the app on my phone, pull to refresh doesnt work?

    I am testing on android lollipop.
    I through the latest version of ionic supported pull to refresh with native scrolling?

    • Perry Govier

      It does. Can you share a code example that reproduces the issue?

  • Álvaro

    Native scroll is really cool. The only problem it has is that the keyboard hides the inputs in long forms and blocks any scroll on the screen.

  • http://sahay.co/ Adi

    What’s the latest on native vs. js scrolling? This article could use an update for ionic v1.0.1 and current iOS/Android versions.

  • udeep shakya

    I am using ionic v 1.0.1. I placed overflow-scroll=”true” in ion-content which contains ion-list of ion-cards (with ng-repeat). The scroll performance is really better compared to when JS scrolling is not enabled. It works really well in Android 4.4.2 (when without pull to refresh) except as Alvaro mentioned below, the keyboard hides the inputs in the long forms. With pull to refresh, the content is sometimes zoomed, when I try to pull to refresh. In Android 4.2.2, there is another problem. The scroll.resize doesn’t resize the content (after infinite scroll) in Android 4.2.2. For now, Im using ionic scroll which is slow but at least, infinite scroll works. I wish to see infinite scroll, PTR working well with JS scrolling in the low-end devices too.

  • Vance Feld

    you want to use collection-repeat if you want a x or y only scroll to be performant. http://ionicframework.com/docs/api/directive/collectionRepeat/

    • http://nicholls.azurewebsites.net/ Juan David Nicholls

      Is possible create a dynamic directive to replace to ng-repeat or collection-repeat depending of platform? (Android and iOS with collection-repeat, but Windows with ng-repeat)
      Thanks!

  • Vance Feld

    does native scroll work with ion-scroll element, or only ion-content?