Showing posts with label custom-scrolling. Show all posts
Showing posts with label custom-scrolling. Show all posts

Sunday, June 26, 2011

Implications of iOS 5 webkit-overflow-scrolling

When news of iOS 5 improvements first came out, we were told that Mobile Safari would support fixed position elements and some rudimentary overflow:scroll improvements. I wrote about why, even with these improvements, custom scrolling would still be required. Fortunately for all of us, Apple had some better news to share when the second beta of iOS 5 came out. Finally, we can have native style scrolling in webapps with some simple CSS.

.scrollable {
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
}

This improvement will be a very powerful tool for mobile web developers. It will make it significantly easier for just about any developer to throw together a really slick looking application. What was previously hundreds of lines of complex JavaScript to animate the page is now 2 simple lines of CSS.

What else will change?

Scrolling Quality

Up until now, almost every scrolling library has tried as hard as possible to replicate iOS native scrolling. As far as I can tell, the only reason that Scrollability even exists is because Joe Hewitt figured he could do a better job of replicating native scrolling than iScroll. With this now natively supported by Mobile Safari, we can all stop worrying about these discrepancies and focus on real work :)

Something less talked about is the rending and GPU overhead that is caused by custom scrolling implementations. Often all of the transforms introduces a lot of flashing in the application when content is re-rendered. Scrolling also gets slower the larger the DOM gets. Presumably with the native support all of these problems will go away, and the user will just have a consistently smooth scrolling experience.

Pull down to refresh

Two weeks ago I wrote about the various pull to refresh implementations on the internet and why I wasn't happy with any of them. Since then, Mobile Gmail pushed an update that includes a really slick pull to refresh widget. Every pull to refresh library that I know of right now is implemented as an add-on to some scrolling library. This is because the pull to refresh components have a high level of interaction with the scrolling components. It is likely that everyone is going to have to rewrite their pull to refresh code to work in the absence of custom scrolling.

I think it won't be at all difficult to rework the widget to work properly, but we might see some applications take a bit longer to migrate to the built in scrolling because of issues like this.

Sticky table headers

Sticky table headers could be a little more troublesome depending on exactly how the built in scrolling is implemented in Mobile Safari. For an example of what I am talking about, check out the menu page on Mobile Gmail, how the list section headers stay fixed at the top and animate away as another header approaches. Like pull to refresh components, sticky table headers implementation requires tight integration with the custom scrolling library it is built on top of.

In Mobile Gmail, the positions of the sticky headers are recomputed on every touchmove event, and on a repeating interval if momentum is in progress. The same can easily be done with the built in scrolling if the browser publishes accurate scroll events. If not, we can maybe estimate when the page might be flinging based on touch events.

Tap to top

Tap to top is a standard gesture recognized by most (all?) iOS native applications that will scroll the current view to the top. When a user taps the top bar in Mobile Safari, the page will scroll to the top and the URL bar will become visible. Ideally the overflow:scroll element  on the page will also be scrolled to the top. Mobile Gmail and Scrollability both support this gesture by listening to scroll events, and determining if the scroll event was from the user dragging the page or tapping the top (based on time of last touch event anywhere in the document).

It is possible that the new built in scrolling will natively support scrolling the overflow:scroll areas to the top, but that seems unlikely. If they in fact do not, then devs might have to use some hacks to continue supporting a tap to top feature. We can still detect the tap to top gesture just as easily, however you can't apply a webkit-transition to the scrollTop feature (now required to change the scroll position). It might be necessary to change the transform to do something like this:

function tapToTop(scrollableElement) {
  var currentOffset = scrollableElement.scrollTop
  
  // Animate to position 0 with a transform.
  scrollableElement.style.webkitTransition =
      '-webkit-transform 300ms ease-out';
  scrollableElement.addEventListener(
      'webkitTransitionEnd', onAnimationEnd, false);
  scrollableElement.style.webkitTransform =
      'translate3d(0, ' + (-currentOffset) +'px,0)';
    
  function onAnimationEnd() {
    // Animation is complete, swap transform with
    // change in scrollTop after removing transition.
    scrollableElement.style.webkitTransition = 'none';
    scrollableElement.style.webkitTransform =
        'translate3d(0,0,0)';
    scrollableElement.scrollTop = 0;
  }
}

Tuesday, June 7, 2011

Why custom scrolling is still required with iOS 5 overflow:scroll

Apple just announced a bunch of improvements that would ship with mobile Safari in iOS 5. You can find most of them here. I was primarily interested in the bits about position: fixed and overflow: scroll, as I have authored my own custom scrolling code for iOS devices (and look forward to not needing it anymore).

It seems like a lot of people have gotten all excited about overflow: scroll and position: fixed, thinking that these improvements are going to make custom scrolling unnecessary. However the way that Apple has developed these features does not solve all the same problems that custom scrolling does.

Custom scrolling solves three problems.

  1. Gives the webapps a fixed elements (like top/bottom toolbars)
  2. Faster scrolling (because default safari scrolling is slower than native apps)
  3. Independent scrollable areas

Points 1 and 2 are intended to give webapps a more native feel. Great for those that believe they should be able to deliver top quality apps to their users through the web. Point 3 is the lesser thought about issue that is required for something like Gmail's two pane UI.


What issues does the new features address? Really only number 1 (giving webapps fixed elements). This can now be achieved by using position:fixed. Number 2 will still be an issue because the rest of the application will scroll by a regular webpage... maybe not a show stopper for many developers. You would think that number 3 would be solved by the new overflow:scroll support, however the overflow:scroll comes without scrollbars, or inertial momentum. In fact the only improvement for overflow:scroll seems to be that you can scroll with one finger now instead of 2.

This is quite disappointing. In the Android world, the browser has supported position:fixed as of 2.2 (Froyo), which solves issue 1. Issue 2 has never actually been an issue on Android because the browser scrolls fast by default. Issue 3 is resolved on Android in version 3.0, with the introduction of overflow:scroll. The PlayBook also supports position:fixed and overflow:scroll. This leaves Apple pretty far behind in terms of giving developers the tools they need to build rich layouts and interactions into their mobile webapps.