I’m currently enrolled at Thinkful.com in the Angular course. I’m well over half-way through and have been applying Angular to my work projects with great success. One thing that I needed to do was to have scrolling views in my hybrid apps while having other areas of the app remain static. My future goals involve using Ionic – which handles scrolling easily enough, and I suspect, in the exact same way I’ve done it here – but I’m a logical step-by-step kind of guy so for now I’m content with learning Angular and rolling my own UI. That being the case I thought to search for the “Angular” way of getting views to scroll and tried a few of the custom directives available on the Internet.
The easiest to set up was ng-scrollable which technically worked but lacked the finesse of the vaunted iScroll. I also tried angular-iscroll but without much success. I reverted to the usually reliable iScroll but Angular didn’t want to play nicely with it. I then reverted to ng-scrollable thinking I could revisit it and proceeded with my other layout duties only to find that ng-scrollable injected too much crap into the DOM which broke a previously working flex-box-based layout. Attempts to rectify the layout proved to be a waste of time. So, I removed ng-scrollable and instead pursued a native / pure css solution.
So lets get back to what I wanted – native-like smooth scrolling with inertia. The answer can be found via CSS by creating a class with the following properties (your wrapping container must have a set width / height, and a setting of “overflow:hidden” on the wrapper will kill scrolling):
overflow-x: hidden; // Control how to clip the container's content.
-ms-overflow-style: -ms-autohiding-scrollbar; // configure overflow scrolling behavior for IE 10
-webkit-overflow-scrolling: touch; // The magic happens here
Each of the above styles are configured as follows:
- auto – Non-inertia scrolling. Scrolling stops as soon as your finger no longer touches the screen.
- touch – Use inertia-based scrolling, the faster you flick the scrollable content the faster it scrolls but continues to a deaccelration scroll whne your finger stops touching the screen. I find this to be the desired behavior as its closest to native on Mobile.
overflow-x, overflow-y – These properties specify how to treat overflowing content via one of the following values:
visible – Indicates the content is not clipped, it may be rendered outside the content box.
hidden – Indicates the content is clipped and no scrollbars are provided.
scroll – Indicates the content is clipped and desktop browsers use scrollbars whether or not any content is clipped. For hybrid application development the scrolling behavior mimics native scrolling where scroll bars don’t appear unless you interact with the scrollable content. On Android at least the scrollbar overlaps content so you should add padding to account for it. On desktop the scrollbars use up additional space within the scrolling wrapper.
auto – Depends on the user agent – meaning that you should expect the native behavor for the overflowing content.
I’m not too concerned with IE in my hybrid app development but here are the configuration options none-the-less:
-ms-overflow-style – Sets the scrolling behavior for overflowing elements in IE (copied from MS).
- auto – Indicates the element inherits its -ms-overflow-style from its parent element
- none – Indicates the element does not display scrollbars or panning indicators, even when its content overflows. Unlike overflow: hidden, elements with -ms-overflow-style: none can still be scrolled via touch panning, keyboard, or mouse wheel.
- scrollbar – Indicates the element displays a classic scrollbar-type control when its content overflows.
- -ms-autohiding-scrollbar – Indicates the element displays auto-hiding scrollbars during mouse interactions and panning indicators during touch and keyboard interactions.
If using this on Android / PhoneGap be sure to install the Crosswalk plugin so that you don’t have to worry about compatibility with older webkits.
Also, it is worth noting that sometimes it wont work unless you apply the webkit-specific styling directly to the element like so:
<div id="comeContent" style="-webkit-ovrflow-scrolling: touch;">...
Also worth noting is that if the content of the scrolling element changes that you may need to force the content heights to be recalculate on iOS by inserting a psuedo-element using a simple calc() function to determine its new height:
Other methods of forcing a screen redraw may work as well.