> iScroll
The overflow:scroll for mobile webkit. Project started because webkit for iPhone does not provide a native way to scroll content inside a fixed size (width/height) div. So basically it was impossible to have a fixed header/footer and a scrolling central area. Until now.
This script has been superseded by iScroll 4. This page is kept for historical reasons.

Project info
Project state: ACTIVE (code is actively updated)
Last code update: 2010.10.08 – v3.7.1
Device compatibility: iPhone/Ipod touch >=2.0, Android >=1.5, iPad >=3.2.
Discussion Group
QR Code opens demo page.
Support development
If this script saved your day or you wish to support iScroll and other scripts development you may consider sending some funds via PayPal.
Overview
iScroll was born because mobile webkit (on iPhone, iPod, Android and Pre) does not provide a native way to scroll content inside a fixed width/height element. This unfortunate situation prevents any web-app to have a position:absolute header and/or footer and a scrolling central area for contents.
Luckily mobile webkit offers a powerful set of hardware accelerated CSS properties that can be used to simulate the missing functionality, so the iScroll development started… But there’s no rose without thorn. Making the scroll feel native has proven more difficult than expected.
How to use
First of all we need to prevent the default behavior of standard touch events. This is easily done adding preventDefault() to the touchmove event. Then initialize the iScroll object on DOMContentLoaded or on window load. Here an example:
function loaded() {
document.addEventListener('touchmove', function(e){ e.preventDefault(); });
myScroll = new iScroll('scroller');
}
document.addEventListener('DOMContentLoaded', loaded);
iScroll takes two parameters. The first is mandatory and is the ID of the element you want to scroll. The second is optional and can be used to pass additional parameters (see below).
On the HTML/CSS side the scrolling area needs to be wrapped by an element which determines the scroller actual size. The following is a common tags configuration for an iScroll.
<div id="wrapper">
<div id="scroller">
<ul>
<li>...</li>
</ul>
</div>
</div>
The #wrapper also needs some classes:
#wrapper {
position:relative;
z-index:1;
width:/* your desired width, auto and 100% are fine */;
height:/* element height */;
overflow:/* hidden|auto|scroll */;
}
That’s it. Enjoy your scrolling. Have a look at the source code of the online example to get a better idea of how the iScroll works.
Syntax
The iScroll syntax is: iScroll(mixed element_id, object options).
element_id, can be both an object pointing to or a string with the ID name of the element to be scrolled. Example: iScroll(document.getElementsByTagName('div')[1]) or iScroll('scroller')
Accepted options are:
- hScrollbar: set to
falseto never show the horizontal scrollbar. The default valuetruemakes the iScroll smartly decide when the scrollbar is needed. Note that if device does not supporttranslate3dhScrollbar is set tofalseby default. - vScrollbar: set to
falseto never show the vertical bar. The default valuetruemakes the iScroll smartly decide when the scrollbar is needed. Note that if device does not supporttranslate3dvScrollbar is set tofalseby default. - bounce: set to
falseto prevent the scroller to bounce outside of boundaries (Android behavior). Defaulttrue(iPhone behavior). - bounceLock:, if set to
truethe scroller stops bouncing if the content is smaller than the visible area. Default:false(as per native iphone scroll). - checkDOMChanges: set to
falseto prevent auto refresh on DOM changes. If you switch off this feature you have to calliScroll.refresh()function programmatically every time the DOM gets modified. If your code makes many subsequent DOM modifications it is suggested to set checkDOMChanges tofalseand to refresh the iScroll only once (ie: when all changes have been done). Defaulttrue. - fadeScrollbar: define wether the scrollbars should fade in/out. Default
trueon iPhone,falseon Android. Set tofalsefor better performance. - momentum: set to
falseto remove the deceleration effect on swipe. Defaulttrueon devices that support translate3d. - shrinkScrollbar: set to
falseto remove the shrinking scrollbars when content is dragged over the boundaries. Defaulttrueon iPhone,falseon Android. It has no impact on performances. - desktopCompatibility: for debug purpose you can set this to
trueto have the script behave on desktop webkit (Safari and Chrome) as it were a touch enabled device. - snap: set to
trueto activate snap scroll. - scrollbarColor: changes the color of the scrollbar. It accepts any valid CSS color (default:
'rgba(0,0,0,0.5)'
Note: options must be sent as object not string. Eg:
myScroll = new iScroll(’scroller’, { checkDOMChanges: false, bounce: false, momentum: false });
Snap scroll
When calling iScroll with “snap” option the scrolling area is subdivided into pages and whenever you swipe the scroll position will always snap to the page. Have a look at the screencast to get an idea.
Probably the best way to use “snap” is by calling it without momentum and scrollbars:
new iScroll('scroller', { snap:true, momentum:false, hScrollbar:false, vScrollbar:false });
If you keep momentum, you get a free-scrolling that will always stop to prefixed positions.
To have a perfect snapping experience the scrolling area should be perfectly divisible by the container size. Eg: If the container width is 200px and you have 10 elements, the whole scroller should be 2000px wide. This is not mandatory as iScroll doesn’t break if the last page is smaller than the container.
Methods
- refresh(): updates all iScroll variables. Useful when the content of the page doesn’t scroll and just “jumps back”. Call refresh() inside a zero
setTimeout. Eg:setTimeout(function () { myScroll.refresh() }, 0). - scrollTo(x, y, timeout): scrolls to any x,y location inside the scrolling area.
- scrollToElement(el, runtime): scrolls to any element inside the scrolling area.
elmust be a CSS3 selector. Eg:scrollToElement("#elementID", '400ms'). - scrollToPage(pageX, pageY, runtime): if snap option is active, scrolls to any page.
pageXandpageYcan be an integer orprev/next. Two keywords that snap to previous or next page in the raw. The “carousel” example in the zip file is a good starting point on using the snap feature. - destroy(full): completely unloads the iScroll. If called with
fullset totrue, the scroller is also removed from the DOM.
Best practices
DOM Changes – If scrolling doesn’t work after an ajax call and DOM change, try to initialize iScroll with checkDOMChanges: false and call refresh() function once the DOM modifications have been done. If this still doesn’t work try to put refresh() inside a 0ms setTimeout. Eg:
setTimeout(function () { myScroll.refresh(); }, 0);
Performance – CSS animations are heavy on the small device CPU. When too many elements are loaded into the scrolling area expect choppy animation. Try to reduce the number of tags inside the scrolling area to the minimum. Try to use just ULs for lists and Ps for paragraphs. Remember that you don’t actually need an anchor to create a button or send an action, so <li><a href="#" onclick="..." />text</a></li> is a waste of tags. You could remove the anchor and place the click event directly on the LI tag.
Try to avoid box-shadow and CSS gradients (especially on Android). I know they are cool and classy, but they don’t play well with CSS animations. Webkit on iPhone seems to handle shadows and gradients a bit better than its counterpart on Android, so you may selectively add/remove features based on the device.
Use a flat color for the #wrapper background, images in the scroller wrapper once again reduce performance.
Important: to preserve resources on devices that don’t support translate3d (namely: Android<2.0) iScroll disables momentum, scrollbars and bounce. You can however reactivate them using the respective options.
Bugs and limitations
Form fields do not play well with CSS animations. Countermeasures have to be adopted on a case-by-case basis.
Please use the issue tracker on Google Code to submit a bug report. You can also follow day by day updates on Google Code.
Future developments
- I’m considering Palm Pre compatibility.
- Check for multiple consecutive changes to the DOM to prevent unnecessary calls to the
refresh()function. - Maybe we can achive better performances with lazy loading and pre-fetching. Lazy loading takes care of loading and unloading elements when they are not needed (ie: out of the screen). Pre-fetching can be used to preload all elements to reduce flickering.
FAQ
Q: Why on Android 1.5/1.6 I’m not seeing the scrollbars?
A: On older devices iScroll disables the scrollbars and other effects. You can reactivate them passing the hScrollbar:true and/or vScrollbar:true options.
Q: Why aren’t you adding feature X?
A: I’d like to keep the iScroll as bare-bone as possible, before adding a new feature I carefully estimate the pros and the cons.
Q: I’ve developed feature X, may I send it to you?
A: Please do! It’s not guaranteed that I will add your feature to the script, but I review all code you send to me.
Q: I’m in a hurry and I need feature X to be added to your script ASAP. Can you help me?
A: Have you considered hiring me?
Revisions history
v3.7.1, 2010.10.08 – Bug fix
v3.7, 2010.10.05 – Lock scrolling direction, added bounceLock and scrollbarColor options, size optimization.
v3.6, 2010.08.24 – Bug Squashing Edition.
v3.6 beta 1, 2010.08.10 – Added snap scroll.
v3.5.1, 2010.07.30 – Mandatory bug fix.
v3.5, 2010.07.27 – Added scrollToElement() method, fixed a bug with scrollbars and multiple iScroll instances, a bit of code clean up.
v3.4.5, 2010.07.04 – Prevent JS error on browsers not supporting WebKitCSSMatrix.
v3.4.4, 2010.06.30 – Better orientation detection.
v3.4.3, 2010.06.27 – Bug fix.
v3.4.2, 2010.06.24 – Bug fix.
v3.4.1, 2010.06.24 – Enhanced shrinking scrollbars.
v3.4, 2010.06.20 – Shrinking scrollbars and preliminary desktop compatibility.
v3.3, 2010.06.11 – Code freeze, let’s go for 3.4.
v3.3 beta 3, 2010.06.10 – Full (?!) Android compatibility.
v3.3 beta 2, 2010.06.08 – Better Android compatibility.
v3.3 beta 1, 2010.06.04 – Added Android >=1.5 compatibility.
v3.2.1, 2010.06.03 – Bug fix.
v3.2, 2010.05.31 – Code clean up.
v3.1 beta 1, 2010.05.06 – Added auto refresh on DOM changes.
v3.0 alpha 1, 2009.11.30 – Complete code rewrite. Scrollbars added. Optimized deceleration.
v2.3, 2009.07.09 – translate() replaced by translate3d().
v2.2, 2009.06.18 – Added OS3.0 compatibility.
v2.1, 2009.02.12 – Added refresh() function.
v2.0, 2009.02.03 – Optimized deceleration formula.
v1.1, 2009.01.18 – Removed timers.
v1.0, 2009.01.03 – Initial release.
I recently wrote my own version of this same functinality, but with Prototype for a hybrid iPad native app. I thought I’d review your code to see the difference. Looks good, but I did catch one thing you will want to change:
detecting iDevices should include ipods:
iphone|ipad|ipod
Please share your code
PS: the iPod is identified as iPhone
I’ve used iScroll now for several projects and I love it. I now need to scroll a pane right to left, but it doesn’t seem to allow this. The header and footer can remain top and bottom, but I need the middle pane to scroll right and left smoothly. Any help appreciated.
There’s a horizontal demo in the zip.
I need to use this within an iFrame, but it acts weird when loaded into another page through an iframe. is there any code I can add to make sure it continues to work properly?
I’m using your “carousel” sample, but when I insert a video tag within one of the li tags, (ex: ), the scrolling stops as soon as I get to that portion. The scrolling does work with with an image, but not with video. I’m using all code in the sample, I haven’t changed anything. Do I need to write some custom javascript maybe? Or is scrolling with video just not allowed? Thanks!
If you’re using the default controls for the video embed, you won’t be able to swipe on the video to scroll through the carousel. Your touch events will be used for the video controls (pinch/zoom) instead. If you’re scrolling area is larger then the video you can swipe above or below it to scroll to the next section. You would have to create custom controls for the video if you want to swipe on top of the video to scroll. However, you will loose the default pinch/zoom feature to make the video go full screen.
just tried the demo page in the Android sdk emulator … looks like it works … so i guess it would probably work on an an Android phone too?
Awesome project. One thing I’ve noticed on the simulator (haven’t tried on the actual iphone yet) is that scrolling up will trigger the browser (including the navbar) to bounce (unless scrolling very slowly). Is this an issue using the actual iphone, or simply a simulator side-effect I am seeing?
Hi Matteo,
I have some problems with your script.
I want to create 2pages with a list of items, the pages are next to each-other, and i have a script that detects a swipe(left or right) gesture which lets the 2pages animate to left or to right to show the next/previous page. This works fine.
But now i want to create a scrollable list in each page.
So i have 2 iscroll objects for each page 1.
But now my swipe script doesn’t work anymore?
Can you please help me by saying how to add swipe detection on container where the pages are in. While still being abled to use iscroll too?
Ah i got it working now!
I moved my touch events to the touch events in the iscroll script. Now it works.
Amazing script, but using it disables font smoothing. Really looking forward to a fix for that.
Doesn’t safari support 2 finger scroll of an absolutely positioned div. I admit I prefer context sensitive 1 finger scrolling as you’ve done but isn’t this possible with some event mapping magic instead of all this CSS stuff?
I tried to fake the second finger, but it is not working.
I haven’t tried it but it seems theoretically possible based on
http://pooky.sourceforge.net/data/SafariJSRef.pdf
Very interesting document, I’ll look into it again, but in the tests I made it was not working.
i add iScroll to my project based on webapp.net. they works great together but it left me one problem, webapp.net manage layers with position:absolute; to keep them at the same position and make horizontal transition well, and when i scroll, iScroll always come back to initial position when i release touch, i can’t go down
is there an option to avoid this ?
how to use the spinning wheel with iscroll so that with an onclick event the rows in the spinning wheel app should be shuffled
Hi there!
It’s fantastic. It works even better than a new update of gmail.com for iPhones.
And I’m happy to see that it works on Samsung Bada as well
I tried your Live demo and it worked fine but with a small remark (I dunno maybe it’s a Bada issue not your one at all) – the list does not scroll smoothly. it rather twitches while scrolling.
Really great script!! Using it over & over for iPad development. I would like to request an option for the direction lock. In many cases I actually need to turn it off, so I added the option myself. Since it is such a simple, but useful change, I thought it might come handy for others too. Now I just have to figure out, how o make it behave nicely with gestures for pinch…
Thanks again for your awesome work!
Wow, thanks for sharing this! Dropped in and worked a treat on iPhone, iPad and Android tablet.
First, this is great stuff! Thanks for developing/maintaining this – really useful!
I have used it on one page and things work fine. However now I am thinking of using it across the app, but I have come across the issue with input fields not working with iScroll, which is a showstopper
Any info on when that’s likely to be fixed?
Is there a way to use it for infinite scroll? (something that will load additional elements when we reach the end of scrool?)
I’ve got troubles implementing this and it looks like it won’t work without hacking iscroll internals.
I need this stuff to!
Is there and onBounce event or somehting like that?
This really is a wonderful library but I am really doing a great job of breaking it. I think I finally understand the DOM side of it and how to properly set widths and height and which divs to set them on.
Now I have a much different issue involving the CSS and webkit.
I have a main page that has four quadrants (a div in each) with an iscroll in each one of them. They work perfectly.
On this page is also a hidden iframe. If a user clicks a link, the iframe is displayed and a new table is built within it that also implements the iscroll library and it works great.
Here is the problem, when I do a css display:none on that iframe, all the 4 underlying divs dissable.
I have narrowed the culprit (after many hours of debugging) to be the z-factor in your translateClose variable. It pushes the iscroll divs behind everything. I have tried to google the functionality but have never dealt with the webkit before so this is very foreign to me. If I change the z-value in the translateClose to 1, they do not disappear when I close the iframe but the scroll no longer works.
Can you give me some insight on how to fix this?
Some further explanation….
The structure of each quadrant is <div><div class=”scroller”></div></div>
The div of class scroller is the one I instantiate iscroll on.
Also, in the iframe, is use the iframe.style.display = “none” to hide it. When I hide it, that is when the underlying iscroll elements disappear, not disable as I stated above.
These scroller div appears to be pushed behind the outer div which is why it disappear, but this only happens after the iframe is hidden. I cannot find any documentation that explains where the webkitTransform actually occurs or if it even needs to. Or are you forcing it programmatically somewhere in the code?
Thanks for the help you can provide.
have you tried to give transform3d(0,0,0) to the iframe?
That did not solve the problem. Let me ask a very simple question. If I set the translateClose value to …
has3d ? ‘,1)’ : ‘)’,
all of my disappearing content is solved but the scroll no longer works. The little scroll indicator appears but the list does not move. What else do I need to change to make the scroll work if I make the change indicated above?
Thanks again for the help.
I tried iScroll when there only one neted DIV under the wrapper and scroller. I have new scenarios.
I have nesed 2 DIV tags under the wrapper and scroller. WHen I use this and test it in iPhone. The page literally freezes. I cannot scroll anymore. Any help is appreciated.
Here is the sample structure
[SNIP]
Note by Matteo: Please use the google group.
Hi,
i have an issue with iScroll.
When i launch my Webapp (Portrait-Mode) the scroll content is not working. After, if i rotate the iPhone in Landscape-Mode and switch it back to Portrait-Mode everything works fine.
I do not know where is the problem and how can i fix the problem.
Thanks for the help.
I also have this problem. Can anyone provide fix for this issue?
I really need iScroll because default scroller not available in my case (I have two fixed iframes and one have div, initialed with iScroll). On mobile devices default scroller not available in my case.
The same here … I cannot figure out the problem, I tried the checkDOMchanges but it doesnt help …
I ended up not needing this script. If you have a div that scrolls on your site, just set the overflow to visible for ipad/iphone and then you can scroll with the native swipe action…. here’s the code if you’re using jquery:
$(document).ready(function() {
//iphone and ipad scroll
if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))) $(“#divthatscrolls”).css(“overflow”,”visible”);
});
this probably won’t work if you’re using fixed header and footer.
this is not working for me, can you provide a complete example?
Hey Morgan, do you have an example/demo where we can see this in action?
Thanks! I’d be most appreciative. I’m trying to get my iPhone tab bar to work properly.
p.s. Matteo–thanks for posting this and keeping the conversation going!
Very impressive ,Thanks for sharing!
How can I hide the URL bar for iPhone? Typically I would just write:
window.scrollTo(0,1);
but that doesn’t work once I’ve implemented iScroll. my demo is setup very similar to yours in regards to markup.
Any suggestions would be great. Thanks for the awesome code, I’ll be sure to send you my implementation when it’s complete.
Considering how Sencha has made their scrollview functionality work well with Android, are you considering porting what they’ve done to iScroll?
Thanks for this project!
the code is not working in IE
no, really?!
Matteo, thanks for sharing this. Looks like it could be very useful.
I’m getting some weird behavior when viewing the live demo on Android – namely, the bottom buttons are only about 25% visible (they fall “below the fold”, and are sticky there obviously, so I can’t use them). Additionally, if I turn to landscape mode they are fully hidden. However, if I move back to portrait the window screen is then very small.
This is all on a nexus one. Have you seen this behavior before?
the problem here is in the way Android 2.2 handles orientationchange. Not a hard fix, though. I’m working on it. We have just to be a bit more aggressive when refreshing the iScroll dimensions (putting refresh() inside a setTimeout for example). Generally speaking android seems to work better with onsize than with onorientationchange.
Hi, I’m trying to use your script for a calendar function on our website. I’m really really new, so I’m really sorry if this is really newbie.. but is there any way for the script to snap to a list item, when scrolling? (a preview of the page is up on http://sodasoda.net/test/cal )
Thanks,
Nice script, work well.
I just notice a issue when using ajax and loading remote content : after DOM changed, some element size can change without any event. I got the problem with remote image which need time to load. this result in a wrong offsetHeight i was not able to detect (wait 2sec is not a good solution).
The only way i found was to force a refresh into the touchStart function and set checkDOMChanges false to save cpu.
This work well, refresh is not called to much and i am sure that the offsetHeight is correct.
Ciao Matteo, great job.
I love it. I’d really like to use it for my next website but I was wondering If you have any thought on including a detection routine for FF and IE so that the script automatically apply the full power to Chrome and Safari Desktop & Mobile, and the other browser they can use jquery or other minified framework…
I know I can do ti by myself (in fact is what i’m trying to do) but the other people, and in order to streamline the code what i’m saying is that would be great to have finally a carousel script that works EVERYWHERE. thanks!
I hate to even ask, but is there any chance of making the desktopCompatibility mode work in IE9? Are the necessary events/properties still webkit-only?
FWIW, I’ve looked into this, and it can be barely made to work in IE9 Platform Preview 7 (thanks to the addition of support for msTransform), but I guess the lack of transition support means that there’s no momentum or bounce. Perhaps those features could be built using alternate means, or perhaps MS will get around to supporting them.
Is there some demopage of the Snap scroll as it looks in the screencast? Just what I have been looking for, great!
Hi,
http://www.yourwebsitepreview.com/transout.com/final/products.html
The right hand side menu postions should remain fix , only the content area should scroll. This works well in all the browsers including safari. But the same doesn’t work in iPad.
Unfortunately this script won’t work proper after the iPad update 4.2.1. The scroller-div keeps blank.
Couple of things:
1. You are my hero
2. Anything to keep me from learning Ruby and Sproutcore to accomplish something as simple as scrolling a DIV with one finger makes me love you just that much more.
3. I can’t thank you enough!
4. Once I transfer some funds to PayPal, I am donating some money to this.
BRAVO! YOU ROCK!
glad you found my script helpful, Alex.
One problem tho….
This doesn’t handle horizontal scrolling??!
Please tell me I can get this to work horizontally….let me know thanks!
sure it works horizontally. there’s an example in the zip for horiz scroll
Hi Matteo, I’m developing a mobile site using iScroll and found an issue on Android 2.2 (tested in the emulator). I have a DIV with -webkit-transform properties (scale, translate, and rotate). In Safari it works great, but in Android iScroll seems cause that DIV to loose its transform completely. If I don’t instantiate iScroll the transform appears without changing any other code on the page, so I know it’s the culprit. Any ideas what it would be?
is there a way to have the ‘double-tab zoom functionality’ also with iScrollers?
Thx!
Walter
working on this.
Hi, I’m a italian student and I use your library for a demo project. The library is very nice and usefull. Perhaps I have found a little bug. I use iscroll in a html page with three elements: header, container, footer. Header and footer are div without animation (if I click the div are blocked and I can’t move it). The container is your iscroll. In the container i have a button with a javascript confirm. If I select NO in the confrim message, I return on the same page and if I click on the footer I can move it! Do you know any solutions? Thanks!! bye
Hi, it’s a great scrollbar, but i have following problem:
HTML select form fields do not funktion in the scroll area, e.g:
Option 1
Option 2
Can anybody help me?
I’m noticing that my scrolling objects appear slightly blurry on my iPad (and on the simulator as well) after applying iScroll. However, when i apply it to a div that has a lot of content it appears sharp. Is anyone else experiencing this? How might I prevent this?
Yeah, I’m experiencing that same problem. Anyone have an idea how to prevent this?
For all text use em instead of px