I recently modified the structure of the blog to have easier access to my projects. The iScroll has now a dedicated page, please head to the iScroll project page to get the lastest updates.

I’ve been asked to publish a new version of iScroll even if in development phase. Here you have it, but keep in mind that we are in Alpha1, the script is very rough and not ready for production. Okay, we are finally out of alpha and I’m moderately proud to introduce Beta phase. Please consider that I’m now working on GhostTouch, a framework dedicated and optimized to touch enabled mobile devices. The iScroll is a stand alone version of the scroller I’m developing for GhostTouch.
First things first. iScroll was born because mobile webkit (iPhone and iPod touch mainly, but also Android and Pre) does not provide a native way to scroll inside a fixed dimensions overflow:scroll|hidden|auto element. This unfortunate situation prevents any web-app to have a fixed header and/or footer and a scrolling central area.
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 has started… But there’s no rose without thorn. Making the scroll feel native has proven more difficult than expected. Version 2.x of the script was good enough, but it was lacking a lot of features.
Enough blabbing. Have a look at the screencast I baked for you or point your mobile device to cubiq.org/dropbox/iscroll.
Update 2010/05/06 – 3.1 beta 1: The most requested feature has been finally added. When new content is added or removed from the scrolling area (eg: ajax calls) iScroll automatically sets the correct position to comfortably host the new contents. We are still in beta, please give feedback.
How to use
All you need to do is to initialize iScroll with something like: myScroll = new iScroll('id');, where id is the #id of the element that will be scrolled. You can place it on window.onload or document.DOMContentLoaded.
iScroll automatically detects if you need vertical, horizontal or both scrollbars, but you can force scrollbars hiding with the optional second parameter. Eg: myScroll = new iScroll('id', {vScrollBar: false, hScrollBar: false}); (this prevents both scrollbars to appear).
On orientation change iScroll also refreshes itself and detects if the scrolling area has changed in size. You should add your code to resize the elements on orientationChange as shown in the example.
Other considerations
I decided to remove the scrollbar shrinking effect (ie: when you scroll outside of the screen the scrollbars reduce in size). Can be done with little effort and some frameworks already implement it, but it’s an inconsiderate waste of resources –precious resources– for such a small feature.
The script should now work on Android, too (at least on version 2.1, please give feedback).
The momentum formula I’m using feels pretty natural, I use a completely rewritten (and ridiculously simple) algorithm. If deceleration doesn’t look natural to you, you can try to tweak friction and deceleration parameters on line 273 and 274.
Q: Why aren’t you adding feature X?
A: I’d like the script to work on older devices. Not everyone has a SnapDragon
Plus, I’d like to keep this script as bare bone as possible so it’s easier for you to customize it to your needs.
Q: I’ve developed feature X, may I send it to you? Will you add my code to your script?
A: Please do! It’s not guaranteed that I will add your feature to the script, but I’ll review all code you send to me (matteo [at] this domain). Consider that scripts will be released under MIT license, if this is a no-go for you, don’t send.
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? (matteo [at] this domain)
I'm pleased that my original 
Thanks Matteo for sharing this script with all of us.
I have a problem with the refresh(), when using scroll in div elements (as oppose to just using innerHTML).
It seems to be working ok if the scroll area doesn’t have nested div. I placed a debug statement in the refresh function, and the offsetHeight and the parentNode.clientHeight are set correctly when I don;t have div, and so does the maxScroll.
However, when I placed images using div element using ajax, the calling refresh, the offsetHeight is set to 1, and the parentNode.clientHeight is set to a high number, therefor setting the maxScroll to 0, causing the scroll area to be non-scrollable.
Idea anyone?
I found a walk-around that might help others who had problem with refresh() not refreshing…If I placed a simple text value at the end of my scroll area (which had only sections), the refresh() works fine.
-Gilad
@Gilad, it seems a stylesheet issue. Are all the divs “float:left”?
ok, i reset the content inside the scroller div via ajax, but it seems the hieght of the scroller div does not change accordingly, any ideas?
I can confirm that this script works on the iPad.
What I am wondering is if Google does the same thing on maps.google.com. The block on the left hand side which fills with search results (hover over a major city then search for “burger”). On the iPad in safari (not the maps app), if that search results block overflows, you van scroll just the content of the block. I tried to figure out how they are doing it, but could not. My guess is they are doing CSS transforms as well. Seems more fluid than your script, which makes me wonder if they are doing it differently.
I’m building a prototype ipad webapp similar to the gmail webapp for ipad and using this script. it works fine on the ipad. the only problem is that I’m using jquery to reload the floating (with external html files), which works as expected, but the height of the div doesnt change accordingly with its new content, there for I can’t scroll to the end. Any ideas?
I would very much like to know how google is doing 2 independently scrollable columns in their gmail interface.
It even works with multitouch.you can scroll both columns at once.
If anyone can provide a simple ipad example with 2 scrollable columns and a static header, that would be much appreciated.
Webshotspro:
I’m working on something like that as we speak, using this script. I looked at the gmail soucecode and I don’t understand it. I noticed that the developer.apple.com has the same thing when seem on the ipad, I managed to get the code and it is 95% (if not, 100%) javascript. I don’t know much about js. anyway, I can send you the template I’m making if you’d like. email me (pedro.tma@gmail.com)
If I see it right they use the same technique used for iscroll. They just scroll images though (set of tiles actually). That’s why I suppose it is so smooth (I just had a quick look, sorry).
@Matteo thanks for your reply.
I added “float:left” to all my divs but that didn’t help either. Do you have other suggestion?
Thanks,
-Gilad
Did you already had a look at this?
i think it might help you:
http://gist.github.com/358506
http://gist.github.com/358507
It doesn’t work… It doesn’t want to scroll. I just copied the javascript code to my already existing javascript document, and called it. Can anyone help me out?
It’s at: http://tb.gdscei.com
When loading new content into the scrolling div via ajax how can i get the page to scroll back to the top when the new content is loaded? I have the loader script in a separate .js file and cannot figure out what to call to do this. I can add this.scrollTo(0,0,’0′) inside the iScroll.js to preform this. Any help would be greatly appreciated. Thanks!
@frup: if you initialize iScroll with
var myScroll = new iScroll(….);
just call myScroll.scrollTo(0,0,’0′) when ajax is done.
Just providing feedback:
Neither the demo nor ghosttouch are currently working for my one-year-old Android device: Google Ion (equiv. to HTC Magic) running Android 1.5.
On the demo at http://cubiq.org/dropbox/iscroll, the div does not scroll. I do see both the vertical and horizontal scrollbars appear after the first touch.
On ghosttouch, at http://tr.im/QKuz, I don’t see the list appear, but I do see the header. The header does not stay in place while scrolling, however.
This guy seems wrote something similar — still not *quite* right, but very close: http://doctyper.com/archives/200808/fixed-positioning-on-mobile-safari/
@Bill Fisher: have to check… but Android 1.5 doesn’t support translate3d(). Maybe can be easily solved using translate()
Matteo thank you so much for providing the script. I am running into a slight problem and was hoping you or someone else could help me. On the initial page load my scrolling content works perfectly, however I have a bunch of navigation links that jump to anchors throughout my content. For example, <a href=”#SECTION_15″>Section 15</a> and once I click (tap) on that the scroll goes haywire. It won’t let me scroll above or below a certain (arbitrarily random) part of the content and other links jump to the wrong part of the page. Do you have any idea what’s going on?
@devhead11: you should jump to contents with scrollTo(), not with anchors.
This is great, thanks.
One issue though, which is not a problem with the script as such.. is that if there is a textarea in the scrolling div then it seems to want to scroll the whole page before it fires off to iScroll.
I’ve tried document/window/thetextboxid.addEventListener(e){e.preventDefault();} and that works for all but the textarea.
Does it have different listener events?
I’ve set overflow:hidden on the body too but it seems to like to create some slack space as it scrolls.
Thanks.
@Matteo – Thank you for the quick response. I am having a hard time figuring out what would be the best practice for getting the Y position of an element? I’ve tried doing a bunch of different things with no luck.
I’ve been using an earlier version of this script for a few months now, excellent work. Recently, however, I’ve begun to experience a bug that I just don’t understand.
The scroller div seems to be getting duplicated on top of itself. Then the bottom copy seems to scroll, while the top copy sits still, superimposed over the scrolling copy. There is only one occurrence of the scroller div in the source code, and I can’t figure out how else this could be happening…
Note that this bug was not affected by upgrading to the latest version of your script.
@devhead11: have a look at the contact list example on this very same site =)
@Billy Duke: I can’t really duplicate your problem. Maybe is something related to your html/css structure.
This is so cool. Such great stuff. Congratulations…. but…
jqTouch…
I’ve tried to add it to my jqTouch page and I just can’t get it to work. I lose scrolling on everything, (including my scroller div).
Please can anyone explain how best to use this great script within a jqTouch page?
I see I’m not the only one who can’t figure it out!
Pretty please!
Thanks for this resource – is there a way to get the “header” to sit on top of the “wrapper” so that the information scrolls under it? Think semi-transparent header where you can see the content underneath when it scrolls. I was thinking it might have to do with z-index’s and putting the header div after the wrapper div is closed, but I can’t get it to work. Maybe someone else can help?
Thanks
Well, to answer my own question – it works.
@matteo thanks again for this!
Do you know of any way to keep the tap-highlight effect when a link is tapped inside an iScroll element? It seems that preventDefault disables it so there’s no feedback when something is tapped. Everything else works great — this is just the last thing I need.
I moved these two lines to touchmove instead of touchstart,
e.preventDefault();
e.stopPropagation();
this seems to let you use comboboxs and drop down boxes and still scroll
@Richard Poirier: add a “tap-highlight” class to the target element on touchstart, remove it on touchmove or touchend.
Hey man great script, I am using it to build an iPad app so far so good but im having problems with the refresh() function. I keep getting the error “myScroll is undefined” whenever I try to complete an jaxa request. Heres my request code:
function displayResult(id) {
var url = ‘displa.php’;
var pars = ‘id=’ + id;
new Ajax.Request( url, {method: ‘get’, parameters: pars,
onComplete: function(response){
Effect.Fade(‘mainContent’, { afterFinish: function(){
Effect.Appear(‘mainContent’);
$(‘mainContent’).innerHTML = response.responseText;
myScroll.refresh();
}});
}
});
}
I have tried a bunch of stuff with no luck and without this bit working I don’t know what to do please help!!
Hello Matteo,
First of all, I have to say this thing could revolutionize Iphone web apps and compete very much with the native applications. I am very much thinking of using it in one of my current works.
Before starting, like asked before by someone else but saw no reply, is it possible to add text box in the FOOTER and it moves up when the cursor is in that, like in SMS application of Iphone??
Your reply would be of great help.
Thanks
I don’t understand, I try to fix horizontal move, but it can’t want to stay fixe.
In fact, I’m trying to make a slide like in iphone apps. I have a contener wich have a content (the scroller window.
The content have 650px width, I’ve got two div in this content, wiches float at left.
Whe I click to the first the second apear with a slide of the first to the left.
My init :
var myScroll;
function loaded() {
setTimeout( function() {
document.ontouchmove = function(e) { e.preventDefault(); return false; }
myScroll = new iScroll( document.getElementById(‘content’), {vScrollBar: true, hScrollBar: false} );
}, 100);
}
window.addEventListener(‘load’, loaded, true);
Can you give more information.
I saw in the different coment :
myScroll = new iScroll( document.getElementById(‘content’),’y');
or myScroll = new iScroll( document.getElementById(‘content’),’x');
I try there, but no effect.
Thanks for this good scroll script !
To make it work on both iPhone and Android 1.5 I changed all translate3d(x,y,z) into translate(x,y)
and change those 2 lines in iScroll.prototype
setPosition: function (x, y) {
[...]
this._x = (x!=undefined && x !== null) ? x : this._x;
this._y = (y!=undefined && y !== null) ? y : this._y;
[...]
Cheers,
Lorenzo
Awesome script! Any ideas what might be causing the stuttering when scrolling on an ipad? I have also noticed that the scrollbar does not have rounded edges, they are squared off. Is this intended?
Thanks,
The scroller is awsome, im just having one problem. When new content is loaded in the scroller and i go back the scroller goes blank.. any ideas?
Great script, but a couple of problems that are still in the latest version ( 3.1 beta 1)
-text in fields are smudged/garbled while typing, some times the characters are invisible
-select boxes do not work. (I have tried the two solutions posted above but both do not work)
@James: I can’t replicate your issue. Does it work properly on the simulator or it’s a problem of the real device only?
@Thomas: I need more details, can’t understand your issue.
@John: I noticed that the garbled text is most of the time related to the HTML tag structure. Try to keep a strict xhtml document and it should work. I converted all tables to divs for a client and the text is not garbled any more. Also try to always give a background to the elements (do not use “transparent”).
I have tried to incorporate this with JQTouch, and I lose scrolling on absolutely everything. Have you figured out a solution to this?
The scrollbar issue was a CSS typo on my part.
Stuttering was a bad reference. What appears to be happening is that slow scrolls work fine. Scrolls where I just move up and down and don’t take my finger off the pad works great as well. When I do a fast scroll however, there is a delay and the screen will scroll to either the top of bottom of the scroll height depending on the direction of scroll.
This is just great, thanks a lot!
I’d like to use iScroll to be able to use scroll a fixed table header row and column with just 1 finger instead of having to use a two-finger gesture: http://acatalept.com/common/test/fixed-table.html
I’m failing to get the fixed “header row” and the fixed “header column” to scroll with the table being scrolled (since the “onscroll” event of the scroller-div is not available anymore when using iScroll).
Any suggestions on how to accomplish this (having additional divs besides the scroller div which scroll automatically when the main div is scrolled, the first vertically, the other horizontally?).
Any help is greatly appreciated!
@Matteo
The new version of iScroll which refreshes itself on ajax addition works as desired and its cool ! But the problem is, when one is doing some Dom node manipulations, it appears to be keeping safari busy doing probably refreshing. This is what it appeared to me. I will update if I come up with something specific. Thanks !
This is excellent work. Any chance of running it through jslint to clean it up? Curious as to why you refer to both this._x/_y in your code while also using the this.x/y getters.
I ask because jslint does not like the getters (and since it’s unlikely that they’re meant to be an external interface they seem superfluous) and because I’ve augmented your stuff with the ability to use Dojo’s DnD functionality. Thanks.
@Mayank, we could add a timeout to the refresh() function, so it is basically called only once if many consecutive DOM modifications are done. Or we could add a refreshON/OFF function to be called programmatically before intense DOM modifications. That’s why I initially didn’t integrate the auto-refresh functionality.
I’ll try the “timeout” path and see if it works.
@cpr, yes a clean up is definitely needed.
I’m making a website that has a horizontal scroll which I have working perfectly with iScroll, how ever, and I’m sorry if this has been stated before, but none of the other native gestures work. For example the pinch and vertical scroll dont work when iScroll is included. I only have iScroll for on section of the site, why would it effect the vertical scroll of the browser? Thanks
Cool. Question: How can I turn off the bouncing effect?
(Seems like the options already carry a flag for deactivating it but it’s not (yet) implemented?)
@Jared: gestures have to be implemented programmatically (sorry, no way to have both scrolling and native gestures)
.
@Jean: that functionality will be added soon (thanks for the heads up).
It appears that new content is loaded as you scroll into new areas, but it’s not unloaded from old areas you’ve already been to. This seems to cause memory problems for very big areas. Is there any way to unload content as you scroll away from it? I am using Version 3.0 alpha 5, by the way.
Nice job
@Eli: Please elaborate. Can you send me your code by email. BTW, always try the latest beta.