Prior to jQuery Mobile 1.1, true fixed toolbar support was contingent on native browser support for the CSS property overflow-scrolling: touch
, which is currently only supported in iOS5. As of version 1.1, jQuery Mobile no longer uses this CSS property at all. We've removed all internal usage of this property in the framework, but we've left it defined globally on the $.mobile object to reduce the risk that its removal will cause trouble with existing applications. This property is flagged for removal, so please update your code to no longer use it. The support test for this property, however, remains defined under $.support
and we have no plans to remove that test at this time.
Currently, both the page you're viewing and the one you're navigating to are sitting next to each other in the viewport, which lets us leverage native scrolling for the broadest possible device support. The downside to this approach is that since both pages share the same viewport, when a page transition starts, we must first scroll to the top of the document, then start animating to ensure that the pages are lined up vertically. If you hit the Back button, we need to scroll up, transition, then restore the previous scroll position. Since mobile browsers are pretty slow, these scroll movements can detract from the flow of the experience.
The way to really improve this situation is to have both pages in separate containers, each with its own internal scroll bar. The means no more scrolling the document or needing to restore scroll positions for a smoother experience. It also has the benefit of making fixed toolbars very easy to implement by simply placing them outside the containers with internal scrolling.
To leverage iOS5′s support for a touch-targeted version of overflow:auto
which allows for internal scrolling regions with the native momentum scrolling, we've added a feature called touchOverflow that leverages these new CSS capabilities to enable us to bring both true “fixed” toolbars and super smooth transitions to iOS5, all by using web standards and very little additional code.
A feature called touchOverflowEnabled
is designed to leverage the upcoming wave of browsers that support overflow scrolling in CSS. Note that this feature is off by default to give us more time to test and debug this for best performance but we hope to turn it on by default at a later point. Here's how to enable this global option:
<script>
$(document).bind("mobileinit", function(){
$.mobile.touchOverflowEnabled = true;
});
</script>
When this feature is activated, the framework looks for browser support for both the overflow:
and -webkit-overflow-scrolling:touch
CSS properties. In browsers that support both, it switches to a dual page container model with native overflow: scrolling within each, which brings true fixed toolbars smooth transitions. Coupled with iOS’s already excellent hardware-accelerated transitions, it's now possible to build interfaces that are very close to native performance.
To demo this feature, check out this page in iOS5.
Nothing is perfect, especially a new feature, so there are a few downsides to keep in mind. When activating this feature:
overflow:
in iOS5. This was a pretty random phenomenon but is not acceptable so we've added a translate-z
CSS property which forces iOS to render the contents. The downside with this fix is that when a transform is applied, all elements are set to position:relative which can cause issues in your layout.-webkit-overflow-scrolling:touch
property seems to disable the events to scroll you to the top of the page when the time is tapped in the status bar. We hope Apple fixes this because it's a very useful feature.overflow:
and -webkit-overflow-scrolling:touch
properties are set, iOS appears to ignore any overflow:hidden properties on the parent, which is the page in our case. So if you have an image or code block that is wider than the viewport, horizontal scrolling will be seen. Yes, but there’s a catch. Both Android Honeycomb and the Blackberry PlayBook support overflow:
properties, but we found in testing that their implementation of overflow wasn't smooth enough, so pages would stutter and hang during scrolling, leading to an unusable experience. We're working with device makers to ensure that they are included when performance improves.
More importantly, targeting overflow correctly is a major issue. If we simply placed an overflow: auto
CSS rule on the pages, other popular mobile platforms like older versions of Android and iOS would essentially just clip off the content and make it effectively inaccessible (yes, you can do a two-finger scroll gesture in iOS but nobody knows that). The smart thing about Apple’s implementation for iOS5 is that they added an additional CSS property -webkit-overflow-scrolling:touch
that allows us to test for this touch scrolling property and, if supported, add in the overflow
rules for just those browsers. This is the only safe way to target overflow without resorting to complex and unmaintainable user agent detection.
We will be working with device and browser makers to encourage support for both these CSS-based properties because we strongly believe that this a critical piece needed to build rich mobile web apps. The project will add any vendor-prefixed additions to touch scrolling property if, for example, Opera, Firefox or Microsoft added this support. Once people see how much better page transitions and fixed toolbars are on iOS5, we’re hoping this will be supported quickly by other browsers. JS-based scroller scripts may still have a place in this new world as a polyfill for browsers that don’t yet support these new CSS capabilities but we see this as a brief, interim tool in the evolution of the mobile web.
Generally touchOverflow is only enabled on devices that support touch-scrolling of overflow areas, not desktop browsers. This can make it difficult to debug problems with the touchOverflow feature. To enable touchOverflow on all browsers, use the following code:
<script>
$(document).bind("mobileinit", function() {
$.support.touchOverflow = true;
$.mobile.touchOverflowEnabled = true;
});
</script>