> Scrolling div for mobile webkit turns 3
I’m pleased that my original iScroll was useful to many. In the past months I received dozens emails asking for new features and bug fixes. I think it’s time to start developing a new version of the scrolling div for mobile webkit with added functionalities.
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)
Thanks for this, it’s let me develop a good fixed layout for the iPhone. It’s broken on an Android simulator for me, still looking into that.
The site I’m working on is meant for many phones, it uses Javascript to make links load dynamically. This functionality broke when I added iScroll; I fixed it by changing the final argument to the initEvent call in the onTouchEnd method to true, allowing the click event to be canceled. Any reason it shouldn’t be cancelable?
Here’s how we were able to fix the Android problem (only the first event would scroll):
In onTouchEnd function, comment out this line:
//document.removeEventListener(‘touchend’, this, true);
Anyone had luck with the following?
-preventing horizontal scrolling on elements that aren’t wider than parent (it is a To Do on the creator’s list)
-clicking links that are within the iScroll region:
specifically, I’m trying to set up a rule in onTouchEnd function that if the move was fewer than N number of pixels set this.moved to false so the click is handled. A) Is this a good approach and B) if not, what would be a good solution to filter “unintended scrolls” so links are available?
@Jason:
// Vertical scrollbar only (horizontal is disabled)
myScroll = new iScroll(document.getElementById(‘scroller’), ‘y’);
reguarding the other issues I’m a bit busy at the moment, but I’ll be back on iScroll next week. So stick around!
is there an easy way to stop the scrolling to the right and left at the moment?
This is exactly what I was looking for to start developing for the iPad – I do have one request. I would like to have the ability to lock the x dimension entirely. I like your implementation of the scroll bars in your last release; however, as I’m scrolling vertically, I’m also pushing the content slightly to the left or right, revealing the gray background on the sides. I want to completely lock down any horizontal movement. (or vertical for that matter if I’m in a horizontal scroll need).
I will dig into the code tonight a bit to see if there is an easy fix but I thought that I would put this out here as a feature request for future versions – great job
Dan
Debugging
I tried loading this in safari and change the user mode to mobile 3.1.2 to see if I can get to work on my machine; however, I get no movement on the screen. How are doing any debugging work with this script? really missing firebug about now
Dan
Awesome script, Matteo, but I’ve noticed one thing:
The HTML ‘select’ form item doesn’t work when it’s inserted into the scroller div. It displays as you’d expect (first item shown in a box with an arrow to the right, the standard styling), but it doesn’t register any touch events. To make sure it wasn’t my HTML that was at fault, I copied all the code from inside the scroller div into a new page and it was fine. I added the meta tags (no scaling, device-width, web-app-capable, etc) one by one and it still worked okay – so I can only conclude that iscroll.js is causing the problem.
Tested it with both v.2 and v.3 of the scroller script. Radio buttons are okay, as are checkboxes and textfields.
Any ideas about how to get select form items working would be great
Sorry to only comment when I noticed a problem! Despite this, though, it’s still an outstanding acheivement, excellent work.
Cheers,
Luke.
Luke, see Comment
#19
Date: 2009/12/07 @ 19:19
By: Udi
Fixed it for me (manually edit iscroll.x.x.js, I’m using 3.0a and adding those four lines fixed it.
v3.0a5 works perfect inside an iframe!
Outstanding, Matteo!
Now there is a small problem with two or more scrollable divs at once:
The scrollbars will allways show on the last scroller, all of them..
Your muitiscroll example shows this problem also..
Is there an easy fix?
hi there, im stuck trying to stop it from scrolling left and right, any help would be perfect…!
@steve morris:
Look at paul’s posts #37 & #38. Works great!
Textboxes inside the scroll area get kinda garbled when you type in them. Any idea why?
Okay guys, sorry for all the not replied questions. I’m assiduously working on an uber optimized framework for mobile devices. Follow me on twitter for updates (http://twitter.com/cubiq). The iScroll will be of course part of whole project. I think that there’s nothing like what I’m going to release, and all will be MIT licensed. Stick around.
There is one small issue with instantiating multiple of these per page (i.e. for use with jqtouch). To fix the scoping issue, the scrollbars definition needs to be moved from the prototype section to the main iScroll function.
function iScroll (el, scrollbars) {
this.element = typeof el == ‘object’ ? el : document.getElementById(el);
this.wrapper = this.element.parentNode;
>> this.scrollbars = {};
iScroll.prototype = {
_xPos: 0,
_yPos: 0,
scrollX: false,
scrollY: false,
maxScrollX: 0,
maxScrollY: 0,
<< //scrollbars: {},
Has anyone tried to add a Youtube video via object tag or video/audio tag. It seems not to work and float on top of everything.
Thanks for giving us this wonderful function.
Regarding drop-down select boxes. I applied the solution mentioned in comment #19 and, while the drop-down worked, scrolling failed. I can get the page to scroll OR have drop-downs but not both.
I placed the suggested code after handleEvent: function(e) and in various other places but with the same result. I see that others have got past this problem, can anyone tell me where I am going wrong.
I am current;y using Version 2.3
Thanks
Addendum…
After looking through the article for the original version I found a comment from Dave (#107) which has cured the problem.
I don’t know if this fix is specific to Version 2.3 but it worked for me.
Make the first line after ‘onTouchStart: function(e) {‘ read as follows…
if(e.target.tagName != ‘SELECT’) e.preventDefault();
That’s all it needs.
..
question.
I’ve been loading data into an iscroll div with jquery to prevent from having 100 iscrolls.. and I just noticed that when you load new data it’s at the same scroll position as before even though all the markup in the div is new..
This would be ok but the problem is that is you’ve scrolled to the bottom , and then loaded new data with less height.. it’s completely blank and you can’t scroll back up ..
I’ve tried everything I could think of to scroll back to the top when loading new data but to no avail .
Any suggestions?
nm,
can add as many divs within the iscroll as needed, so can just swap displays on the divs within the iscroll div if heights are off
Hello,
is that a bug? i want to load more content in the iscroll but i can’t scroll to the end because the iscroll isn’t grow.
@Bartman
I wasn’t having trouble with what you’re describing.
the div you’re using is probably hardcoded height,
add another innermost div to the iscroll that does not have height attribute and load or append your data to That div instead.
Thanks for such a great tool. I am wondering if anyone has solved the problem I’m currently having. I’m trying to build a little page that mimics the demo but only with horizontal scrolling. Once the user would scroll all the way to the end I have an ajax call to populate the “scroller” div with the next batch of data. The problem is with resizing the “scroller” div once I’ve added the new data. I figure that I need to reinitialize the iScroll for the change in width to take effect. Played around a bit but I haven’t found a solution to this that didn’t cause the page to break. Does anyone have an idea on how to do this or point me in a direction?
duh I got it… refresh() does the trick.
@Chris: thats was my problem to. refresh(); Now the iScroll works with Ajax
@dan: Did you find a solution for locking horizontal/vertical movement? This is a big issue with the new version I think..
Hi I’m very impressed by your job,
although I have a few problems. Let me explain: I’m using Jqtouch and only the javascript and css in the index.html works. In my case I would like to create another html linked to the index.html. But when I do that the iscroll does fixe the tab bar but I can’t move mt text anymore. Would you have an idea why?
Ahead, here is how you can fix it:
- var leftDelta = e.targetTouches[0].clientX – this.startX;
- var topDelta = e.targetTouches[0].clientY – this.startY;
+ var leftDelta = 0;
+ var topDelta = 0;
+
+ if (this.scrollX && this.scrollbars.x) {
+ leftDelta = e.targetTouches[0].clientX – this.startX;
+ }
+
+ if (this.scrollY && this.scrollbars.y) {
+ topDelta = e.targetTouches[0].clientY – this.startY;
+ }
This will only enable iscroll to only care about x/y movements in touchmove if the respective scrollbars were enabled. It should fix your issue…
@Bartman: another way of fixing ajax/refresh problems is to put a call to refresh() at the beginning of the onTouchStart function. Basically, make it look like this:
onTouchStart: function(e) {
this.refresh();
…
So you won’t have to care about calling refresh() when your things finally came in from the server. This is quite annoying because the view shouldn’t know when it’s done populating.
@Pascal: Thanks a lot, I’ll give it a try
What’s up with this javascript?
141: get x() {
Is that a mistake, or maybe it’s Safari/iPhone specific?
Once i use this with like a list of items (clickable) once i slightly touch one its scrolls to the top. Thats kinda irritating, is there a fix?
Has anyone using this script faced flicker issues when you have a lot of rows to be displayed in the div?
As already said, I’m working on a whole framework for iPhone. I’m rewriting the scroller at the moment. You can see a preliminary version online at http://tr.im/QKuz (on your iphone, android or simulator). I’ll post more details about the framework in the coming days.
Thanks a lot for this solution!
I was wondering how I could toggle the scroll-ability of an iScroll on and off, I’m still new to jQeury and tried different tactics, but it just doesn’t seem to work.
hi i had implemented this code in one of my project…. but even though scrolling function is there ….. it does not shows the scroll bars while scrolling..can anyboby tell me the reason for this….and can anyone tell me…wat the scrollbars parameter in iscroll method means…
Did anyone use this successfully with jQTouch?
Once I add a wrapper my whole app goes nuts. Instead of just showing the current page, I see the divs I have on that file…
Hi Matteo, thanks for the great work!
I have 2 small issues with 3.0alpha5. Maybe you want to consider changing it:
- Line 276 and 278 seem to be accidentally doubled, I guess you could drop one
- the ‘click’ event triggering on line 356 should be changed from initEvent to initMouseEvent in order to pass clientX and clientY tap positions. Some people (like me e.g.) want to evaluate these values…
theEvent.initMouseEvent( ‘click’, true, false, window, 0, this.startX, this.startY, this.startX, this.startY, false, false, false, false, 0, null );
See https://developer.mozilla.org/en/DOM/event.initMouseEvent
Cheers,
Benjamin
This is working very well for me using code from http://code.google.com/p/ghosttouch/
Only blockers I have now are:
1) scrolling freeze due to a missing touchmove event. I am not sure if I’m scrolling too fast or I am scrolling off the page or what…
2) flashing while scrolling because of images that are outside of viewing area. Once I scroll down completely (8000px), then all images seem to be cached and then I don’t see the flashing anymore.
Keep up the good work!
Heyo,
This looks great. I have a Droid, and would love to help test android compatibility. Currently, the demo you have works for the first gesture, but further drags fail to have any effect. Let me know if I can be of any use to you!
@Benjamin, thanks. Yes there are a couple of lame bugs in the code here and there, but the script you find at http://code.google.com/p/ghosttouch/ is pretty much working. I’ll update the code here on my blog asap.
@Drew, we already found what causes that issue on android. GhostTouch should be working on Android.
man use your two fingers to scroll…:P
It works checkout
http://www.flickr.com/photos/joostvanderborg/3240775419/
i spend my hole day..:P
Hi Matteo,
Great work on GhostTouch! I’m noticing a bug regarding opacity. When I refresh my page sometimes the opacity for the scrolling window is not set back to 1.0. I notice you set the opacity to almost invisible in order to scroll the entire window to the bottom then pop back up again. After it pops back up, it should set the opacity back to 1.0 right? For some reason it doesn’t always do this.
Thanks
First of all thanks for this awesome script.
I got a question I’m trying to have a fixed footer I did this via position:fixed and bottom:0px it works great but the viewport is like at a fixed size.
I tried editing the wrapper height but that didn’t see to work do I have to edit the height in the javascript? or is this something I can do via css?
Thanks again.
Hi,
This script seems to be a great solution to the annoying scrolling div problem on the ipod/iphone. However, it seems to turn off normal scrolling. I have a section of my site as a scrolling div. I still want people to be able to zoom in and out and that means being able to use the usual scroll bars.
As it is, once you scroll in, you can’t move around – is there any way around this? Or is this script restricted to sites that fit completely within the viewport?
Hi Matteo,
I experienced an issue adding another top fixed element at the base of the navigation bar (I’m using JQtouch).
The new element causes the page not to be scrolled completely. The footer part is hidden by the browser toolbar. What’s wrong? How may I solve this problem?
Thanks in advance and Happy Easter.
Fabio
Italy