> iScroll

iScroll v3

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 false to never show the horizontal scrollbar. The default value true makes the iScroll smartly decide when the scrollbar is needed. Note that if device does not support translate3d hScrollbar is set to false by default.
  • vScrollbar: set to false to never show the vertical bar. The default value true makes the iScroll smartly decide when the scrollbar is needed. Note that if device does not support translate3d vScrollbar is set to false by default.
  • bounce: set to false to prevent the scroller to bounce outside of boundaries (Android behavior). Default true (iPhone behavior).
  • bounceLock:, if set to true the scroller stops bouncing if the content is smaller than the visible area. Default: false (as per native iphone scroll).
  • checkDOMChanges: set to false to prevent auto refresh on DOM changes. If you switch off this feature you have to call iScroll.refresh() function programmatically every time the DOM gets modified. If your code makes many subsequent DOM modifications it is suggested to set checkDOMChanges to false and to refresh the iScroll only once (ie: when all changes have been done). Default true.
  • fadeScrollbar: define wether the scrollbars should fade in/out. Default true on iPhone, false on Android. Set to false for better performance.
  • momentum: set to false to remove the deceleration effect on swipe. Default true on devices that support translate3d.
  • shrinkScrollbar: set to false to remove the shrinking scrollbars when content is dragged over the boundaries. Default true on iPhone, false on Android. It has no impact on performances.
  • desktopCompatibility: for debug purpose you can set this to true to have the script behave on desktop webkit (Safari and Chrome) as it were a touch enabled device.
  • snap: set to true to 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. el must be a CSS3 selector. Eg: scrollToElement("#elementID", '400ms').
  • scrollToPage(pageX, pageY, runtime): if snap option is active, scrolls to any page. pageX and pageY can be an integer or prev/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 full set to true, 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.

/Share the joy

/Reactions

    • Author: Nuno
    • Posted on: 2010/07/12
    • At: 18:20

    no need to set the size of the wrapper with javascript… it can be done purely with css. the setHeight function can be dropped.

    • I tried many solutions to have a pure CSS version but couldn’t find a way to have it working on all devices, orientations and modes. If you know how, please share.

      • Author: Antago
      • Posted on: 2010/07/13
      • At: 17:47

      $( “#wrapper” ).css( “width”, $( window ).width() );
      $( “#wrapper” ).css( “height”, $( window ).height() );
      $( window ).resize(
      function()
      {
      $( “#wrapper” ).css( “width”, $( window ).width() );
      $( “#wrapper” ).css( “height”, $( window ).height() );
      }
      );

      • Author: DeDi
      • Posted on: 2010/07/13
      • At: 18:59

      Antago, you’re using jQuery to set the width and height.
      This is the same as using javascript.
      This is no pure css solution.

      • Author: Chankit
      • Posted on: 2010/08/15
      • At: 13:21

      In one of my project, I used 100% width and height for #scroller, with #header and #footer both with absolute position, 100% width and fixed height (e.g. 40px). The scroller works as expected without setHeight().

      I even put opacity 0.9 in #header and it looks terrifc :)

    • Author: Antago
    • Posted on: 2010/07/13
    • At: 17:46

    Shouldn’t “resetPosition” and the “setPosition” functions include “this.setTransitionTime(’0′);” ? The momentum script appears to linger on in some sort of mysterious mode so that if you attempt to use your own scrolling function it becomes jerky.

    I had to call “myScroll.setTransitionTime(’0′);” manually, when in reality it should be included in the main functions

    • Author: Spinlock
    • Posted on: 2010/07/13
    • At: 19:39

    Hi Matteo,

    First off, awesome work on the script. It rocks.

    I’m having a problem using it for one of my projects. When i try and scroll the div, it scrolls (up or down) but then snaps back to the original position. The behavior is very similar to the situation where you are at the top of the scroller and try and scroll up more, and it bounces down, except this happens when i try and scroll down as well.

    Is this something you’ve seen before?

    Here’s the css for my wrapper div –

    #wrapper {
    height: 75%;
    overflow: auto;
    position: relative;
    z-index: 1;
    }

      • Author: Troy
      • Posted on: 2010/07/14
      • At: 01:07

      I was having that SAME problem!

      I don’t know what I did to fix it, but was driving me crazy for awhile.

      My wrapper {
      position: absolute;
      top:5;
      left:5;
      right:150px;
      bottom:5;
      overflow:hidden;
      z-index:2000;
      }

      I jacked up the z-index because I thought that was the problem hahaha

      • Author: Mike
      • Posted on: 2010/07/22
      • At: 02:20

      I had this same problem on a DIV where I was dynamically building a table. The solution was to set checkDOMChanges to “false” and call iscroll.refresh() when my code was finished building the table.

      Hope this helps.

      • Author: Raymond
      • Posted on: 2010/07/22
      • At: 04:44

      Hi Matteo,

      You are doing a great work with the scroller, keep it up !!!

      I have had the same problems than Spinlock,Troy and Mike, contrary to them I have not been able to solve the problem on my own, I am fresh to Javascript and mobile apps and have not developed any major app in the last 15 years and at the time it was assembler and C, no objects, events and all, so thanks for your understanding.

      The situation :
      When I use iScroll I can only move the scroller a little and then it bounce back to the original position.

      What do I use :
      I use iScroll in conjunction with jqtouch.

      What have I tried to address the problem :
      Pretty much everything, including typing blindly any advise from any post I have found on the subject..
      In my latest iteration I have tried to do it the jqtouch way instead of following your example because I was concerned that jqtouch event handling was competing with iscroll for the touchmove event

      My latest code :
      $(document).ready(function(){
      myScroll = new iScroll(‘scroller’,'checkDOMChanges:false’);
      $(‘#scroller’).touchmove(function(e) {
      myScroll.refresh();
      e.preventDefault();
      });
      });

      My latest wrapper:
      #wrapper {
      position:relative;
      z-index:1;
      width:100%;
      height:350px;
      overflow:scroll;

      Explanation of what I think I am doing :
      1) Use jqtouch $(document).ready to build the scroller when the document is ready.
      2)Build the scroller with the checkDOMChanges to false and refresh the scroller only when there is actually a touchmove event that actually affect it.

      Result :
      Same as with every previous attempts, I can scroll only a short distance and the scroller bounce back to initial position as soon as I release it.

      My hunch :
      I have the impression that none of the additional parameters passed to iscroll really function in my environement, I have tried to use ‘ momentum’, ‘shrinkScrollbar’, etc… and never noticed any difference in the behavior, I have also used your own simple example and tried to add this various parameters but none of them seem to modify the behavior of iScroll.

      Sorry for the length of the post and thanks again for your efforts with iScroll.
      -Raymond

    • Options must be sent as object not string. Eg:
      myScroll = new iScroll(’scroller’, { checkDOMChanges: false });

      • Author: Raymond
      • Posted on: 2010/07/24
      • At: 10:09

      Thanks Matteo,

      Although the problem of with the bounce back is still there, at least the options to iscroll are now accepted, Sorry, I did not notice that they where not passed as strings…
      Will keep on testing to find out what is forcing the bounce back.

      Thanks again for your help

      Raymond

    • The scroller “bounces back” if it is unable to get the actual wrapper or scroller size. This is 99% of the times due to a CSS or layout problem (eg: the images have no declared height/width). Try to declare iscroll on window load (instead on $().ready()) with a 100ms delay.

      • Author: Eliot
      • Posted on: 2010/08/03
      • At: 00:57

      float:left; in the stylesheet was a line that was causing mine to bounce back. Removed that and everything worked fine.

      I have another section that is bouncing back but I have yet to find a solution. Will post once discovered.

    • Author: tdskate
    • Posted on: 2010/07/14
    • At: 14:10

    Hmmm… iScroll doesn’t seem to play nice with changes to properties by way of CSS3 media queries…

    • Author: shwe
    • Posted on: 2010/07/14
    • At: 15:45

    It doesn’t work in iPad web pages which have iFrames.

    I think it is not because of the iScroll’s bug. But it is iPad safari’s iFrame related bug.

    If web page has more than one iFrames side by side and if you want to attach iScroll in middle iFrame or right iFrame, user doesn’t get the ‘touchstart’ event.

    Anybody has similar problem with iPad Safari iFrames?

    • Author: Gwyn Judd
    • Posted on: 2010/07/15
    • At: 02:10

    Hi,
    we are using iscroll 3.0beta4 for a web app on iphone – it seems to work great, however we tried to update to the latest 3.4.5 and it breaks all of our jqtouch animations. With the latest version, the animations don’t run and it just seems to “jump” to the next page.

      • Author: Gwyn Judd
      • Posted on: 2010/07/17
      • At: 01:51

      Some more detail on this, we found that commenting out the line below would resolve the issue with jqtouch animations (of course, this would tend to break the area calculation for the scrollbar control, but this is probably resolvable in some other way):

      this.element.addEventListener(‘DOMSubtreeModified’, this, false);

    • There’s probably some event overlapping on dom changes.

      Try the following:
      initialize iscroll with checkDOMChanges: false
      and call myScroll.refresh() after each ajax calls

  • Seems like if a touch event is binded to a div in an iframe. The touch event within the iframe does not enforce z-indexes.

    This means that if you have a modal with higher z-index in the parent window, if you place this modal over the iframe. Visually it will look like it is over the iframe’s contents, however the touch event in the iframe is called first before the touch event in the modal.

    I’m not sure if this is a bug in mobile safari (I am using an iPad on 3.2) or iScroll but I solved it by removing the e.preventDefault() call in iScroll’s touchStart function.

    • Author: Arnaud
    • Posted on: 2010/07/15
    • At: 13:58

    Hi people,

    iScroll is by far the most complete implementation of fixed header/footer with scrolling content I found on the internet. And I’ve been looking for something descent for weeks… Great work !

    I’m trying to integrate it in a GWT project with UIBinder, and I’m really having a hard time making it work. Has somebody done such thing and could provide a class or example code ?

    Thanks

    Arnaud

    • Author: Troy
    • Posted on: 2010/07/16
    • At: 18:55

    Question: What were some of the hacks that people used for form entry inside iScroll? Did it involve binding a touchup to a focus or something?

      • Author: Jonatan
      • Posted on: 2010/07/19
      • At: 14:21

      I’m also having problems with form fields… Anyone?

    • Author: kaskooye
    • Posted on: 2010/07/16
    • At: 19:23

    Hi Matteo,

    As mentioned by Troy and Spinlock, it seems to be a small issue in 3.4.5. _and_ dynamic content (Ajax)

    It fails to correctly scroll the whole wrapper, unless you resize if. This seems to be an invalid computation of the real size of the wrapper height.

    Can you confirm please ?
    BTW, Have nice holidays, you deserve it :)

    Thanks again

    • It works in my tests, I’d need to see some demos about this behavior.

      Also try the following:
      initialize iscroll with checkDOMChanges: false
      and call myScroll.refresh() after each ajax calls.

      It’s impossible to predict all scenarios where iscroll will be used, that’s why you can trigger the check on dom changes on and off.

      • Author: kaskooye
      • Posted on: 2010/07/18
      • At: 16:31

      Thanks a lot Matteo
      I test checkDOMChnages asap.

      Ciao!

      • Author: Troy
      • Posted on: 2010/07/19
      • At: 19:01

      Yeah manually calling refresh() did fix my problem with it bouncing back to the top. I called it when the view was displayed and whenever it resized.

      • Author: Marko Ranđelović
      • Posted on: 2010/07/21
      • At: 20:12

      Hi Matteo,

      I just love your script and it has helped me a lot with the iPad web app I am developing at the moment.

      But, I am also having some trouble with the content bouncing when I try to scroll and, yes, there are changes to the DOM involved. :)

      I tried initializing iScroll with checkDOMChanges: false and then calling myScroll2.refresh() (myScroll2 is one of the scrollers with dynamic content) after the content is injected into the DOM but it doesn’t help.

      Maybe I am not using the correct syntax to specify the options but it still didn’t work after I set checkDOMChanges to false in the iscroll.js file. Can you share the proper syntax for this or do you have any other idea why it might not work.

      Thanks in advance. :)

    • to everyone. If setting checkDOMChanges to false and calling refresh() once the ajax call is done doesn’t work, try to call the refresh inside a 0-setTimeout. Eg:
      setTimeout(function () { myScroll.refresh(); }, 0);

      • Author: Marko Ranđelović
      • Posted on: 2010/07/22
      • At: 10:30

      Hi Matteo,

      Thank you very much for replying but the content still bounces back even after I call the refresh with: setTimeout(function () { myScroll.refresh(); }, 0);… Do you have any idea what might be the problem? I have passed the checkDOMChanges as an object, like you specified…

      • Author: Marko Ranđelović
      • Posted on: 2010/07/22
      • At: 10:38

      Oh, I forgot to mention this: when I flip the iPad and the orientation changes, the content starts scrolling properly. That’s why I don’t understand why the refresh call isn’t helping… :S

      • Author: Marko Ranđelović
      • Posted on: 2010/07/22
      • At: 13:07

      Another update: got it to work. :) Turns out that I had to place the refresh immediately after the function that fades in the inserted content. Earlier, I had placed the refresh call after the function that inserts the content…

      Matteo, thanks again for your help, really appreciate it. And thank you for developing this awesome script. :D

    • Glad it worked, Marko!

    • Author: Adriano
    • Posted on: 2010/07/17
    • At: 15:37

    Hi man, great work… I’m trying to use some anchors and have no success… Any tip?
    Thanks

  • Quick preview http://vimeo.com/13412402
    Ciao!

      • Author: kaskooye
      • Posted on: 2010/07/18
      • At: 16:39

      Amazing as always !
      I love the touch and feel, well done.

      Fun to seen we’re working on quite the same things…
      Mine is more tablets oriented. I should have something to show in 1 or two weeks, a video maybe :)

      Ciao

    • Author: Matt
    • Posted on: 2010/07/19
    • At: 02:32

    I have run into this bug: If I hide either the wrapper or scroller div and then try to populate the scroller dynamically with items, the scroller will break. I need to hide and show the div in my application. Is there a way around this?

    Example:
    function initialize() {
    // iScroll
    document.addEventListener(‘touchmove’, function(e){ e.preventDefault(); });
    myScroll = new iScroll(‘scroller’);
    //hide div
    jQuery(‘#scroller’).hide();
    //
    for (var i = 0; i < 30; i++) {
    jQuery('#scroller').append("Here's a new Line! “);
    }
    //show div
    jQuery(‘#scroller’).show();
    }

    • What do you mean by “the scroller will break”? What does it actually do? Try to add myScroll.refresh() at the end of your function. You may also try to make the scroller visibility:hidden instead of display:none (that is what $.hide() does).

    • Author: Tonci
    • Posted on: 2010/07/19
    • At: 17:19

    Please consider caching the this.element.offsetHeight/Width values in iScroll.refresh() method.

    E.g. in the beginning of the method:

    refresh: function () {
    this.scrollWidth = this.wrapper.clientWidth;
    this.scrollHeight = this.wrapper.clientHeight;

    this.offsetWidth = this.element.offsetWidth;
    this.offsetHeight = this.element.offsetHeight;

    this.maxScrollX = this.scrollWidth – this.offsetWidth;
    this.maxScrollY = this.scrollHeight – this.offsetHeight;
    // …

    And later on in the same method (and the rest of the object).

    • Will do, thanks for the suggestion.

    • Author: John
    • Posted on: 2010/07/20
    • At: 20:22

    Hey Matteo,

    For some reason after scrolling a bit down a page and then selecting a text field, the ability to edit the text does not work. The options to cut,copy,paste or select the text cannot be done.

    (iphone os4, iscroll 3.4.5)

    • Author: Tonci
    • Posted on: 2010/07/21
    • At: 01:12

    Why do you constantly register and unregister for MOVE_EVENT and END_EVENT events?

    Why don’t you register them on startup and set a “this.scrolling” flag in iScroll.touchStart() method? Afterwards, begin touchMove() and touchEnd() methods with:

    if (!this.scrolling) {
    return;
    }

    A general suggestion is to avoid unnecessary instructions such as:
    a) var someFlag = a > b ? true : false;
    It’s the same as:
    var someFlag = a > b;

    b) this.scrollX === true ? codeA : codeB;

    Is a bit faster if you write it like this:

    this.scrollX ? codeA : codeB;

    c) cache results of calls to DOM methods (as I’ve written before) – this will speed things up on e.g. older Androids

    Otherwise, great plugin! I’ve seen it run on iPad, it’s fantastic!

    We’ve found a bug there too: iScroll doesn’t support multiple scrollers per page – you cannot use them simultaneously, i.e. if you’re scrolling one and start the other, they start to behave awkwardly.

    • Thanks for your suggestions. There’s a lot of code clean up needed again. The register/unregister thing comes from some tests done a long time ago (I’d say 1 year, iscroll started on iphone os v2.0). Some coding styles are there to meet a (never accomplished) JSlint compatibility.

      Regarding the multiple scrollers issue, you need to be more specific :) I successfully used dozens scrollers in the same page (here’s an old test I did some time ago http://cubiq.org/dropbox/iscroll/2scrolls.html ).

      • Author: kaskooye
      • Posted on: 2010/07/21
      • At: 19:21

      Tonci,

      I ran into the same behaviour, while using multiple instance of isScroll.
      Here’s what i plan to use, to avoid this.

      IMHO, there only need for one instance of iScroll, because in 99,99 % of cases, you just scroll one area at a time.
      Other gestures involving a multi-panel scroll are far beyond my needs. On the opposite, i need multi scrolling area, but one at a time.

      So, I’m working on an ‘on demand’ hook, which will change iScroll instance’s target.

      Most obvious problem I can see so far, is to keep the wrapper displacment when jumping from one arera to on other, then coming back to the first one.

      What do you all think of it ?
      Ciao,
      Jean-Philippe

    • Author: Marco Paolo
    • Posted on: 2010/07/21
    • At: 11:45

    Sorry for my english…. i have a big problem.
    If I use an image in a div wrapper the iphone scroll correctly but when I arrive to image I cannot scroll….like a “rubber band (elastico) effect”…..
    This is the code….

    Pretty content row 1

    this is my link with problem:
    http://www.gastronomiagalanti.com/prova/

    • Ensure your image has explicit width/height. (sorry can’t access your demo page)

    • Author: Marco Paolo
    • Posted on: 2010/07/21
    • At: 16:06

    Great !!!!!!
    THanks!!!!

    • Author: Q-Zma
    • Posted on: 2010/07/23
    • At: 14:08

    check please iScroll instance if element to which it is apllied — not shown

    • Author: Brian
    • Posted on: 2010/07/26
    • At: 05:27

    Matteo, any feedback on when you might make the next release? Do you think that the fix for the form inputs, such as select box not being clickable will make it in?

    • Author: James
    • Posted on: 2010/07/26
    • At: 20:48

    First of all, thanks so much for the script! I’m having a bit of trouble getting my own implementation to work though. I’m running the following inside of JQTouch. On a desktop browser I get the normal “overflow:auto” behavior except that you can just keep scrolling up or down towards infinity. On mobile Safari, I get a normal “overflow:hidden” behavior. Any ideas anyone? I’m at a loss.

    var myScroll = new iScroll(‘scroller’,{
    checkDOMChanges:true,
    bounce:true,
    momentum:true,
    desktopCompatibility:true
    });
    $(‘#scroller’).touchmove(function(e) {
    myScroll.refresh();
    e.preventDefault();
    e.stopPropagation();
    });

    • refresh()ing on touchmove is extremely hazardous…

    • Author: James
    • Posted on: 2010/07/27
    • At: 20:08

    Basically… I’m trying to get your script to play nicely with jQTouch. Any thoughts, suggestions, etc? I’ve been staring at this for days with no results so really any and all help is appreciated. Thanks in advance!

    • Author: pandakweb
    • Posted on: 2010/07/28
    • At: 11:55

    Hi,Great work,Thx.But when I split my scrolling contents into columns,it bounce back to the original position after I scroll it.The following is the html code:

    Col A

    COL D

    C3R2
    C4R2
    C1R3
    C2R3

    ,when the css file looks like
    “#colstext { display: block; }
    #colstext li { display: block; padding: 0 0 5px 5px;width:74px; height:74px;}” ,
    the page works fine,but if the css file adds “float: left; ” to the li tag,which makes it looks like
    “#colstext { display: block; }
    #colstext li { float: left; display: block; padding: 0 0 5px 5px;width:74px; height:74px;}”,
    the problem accrues.Would you please tell me why?

      • Author: pandakweb
      • Posted on: 2010/07/28
      • At: 12:04

      sorry,I can’t post the html code correctly,I repost it one more time with “《” replace “”
      《div id=”wrapper”》
      《ul id=”colstext”》
      《li》Col A《/li》
      《li》《/li》
      《li》《/li》
      《li》COL D《/li》
      《li》《/li》
      《li》《/li》
      《li》C3R2《/li》
      《li》C4R2《/li》
      《li》C1R3《/li》
      《li》C2R3《/li》
      《li》《/li》
      《li》《/li》
      《li》《/li》
      《li》《/li》
      《li》《/li》
      《li》《/li》
      《/ul》
      《div class=”clsit”》《/div》
      《/div》

    • I’d neet to see a demo page

    • Author: Tonci
    • Posted on: 2010/07/29
    • At: 11:12

    Hi, Matteo!

    One question. Why do you use “instanceof” in iScroll.refresh() method? There’s really no need for it during every refresh. You’re setting this variable either to an instance of scrollbar() or to null.

    Therefore, this should be sufficient:

    if (!that.scrollBarY) {
    that.scrollBarY = new scrollbar(…);
    }

      • Author: mystix
      • Posted on: 2010/07/29
      • At: 22:10

      or better:

      that.scrollBarY = that.scrollBarY || new scrollbar(…);

    • Thanks for the heads-up guys. I can’t remember why I used instanceof, probably the code around changed and now is not needed anymore.

    • Author: Alex
    • Posted on: 2010/07/29
    • At: 23:08

    Am I the only one who experiences blur/quality reduction after viewing a iscroll page with a lot of content (height wise) on the iphone 4?

    • Author: Joel Dare
    • Posted on: 2010/08/03
    • At: 20:05

    I wonder if there is any way to put an iframe inside the scrolling area. I can’t use a div because I need to include a full working website (where the existing relative links work). I’d like to build the header and footer on the iphone itself (using PhoneGap) and then have a web page load in the center.

    I’ve tried various different ways and whenever I add the iframe to the page (or the scrolling div) the scrolling stops working.

    Thoughts?

    • Author: Vitor
    • Posted on: 2010/08/03
    • At: 22:29

    Awesome work, but I have one question:

    Is there a way to use iScroll on a horizontal div without removing the scroll of the entire page?

    I am trying to use it as I mentioned, and it works perfectly, but the counterpart is that I cant scroll my site vertically. :(

    • you should start by commenting line 31 in index.html (not iscroll itself).

    • Author: Scott
    • Posted on: 2010/08/04
    • At: 05:06

    Awesome, awesome, awesome script! The one problem I am still having is the one described a long time ago about the scroll region getting pushed up (thereby pushing my fixed top header offscreen) when the virtual keyboard comes on the screen .

    Has this issue ever been dealt with, or are there any workarounds to fix this?

    • Author: Roberto
    • Posted on: 2010/08/04
    • At: 09:38

    This is my preferred touch scroll implementation. I integrated iScroll-based functionality into my fork of uki webapp framework, http://github.com/rsaccon/uki

    • Impressive work Roberto! Keep going. I’ll soon add a list of projects/websites using iScroll (ie: free linkback for everyone :) )

    • Author: Anuj
    • Posted on: 2010/08/05
    • At: 17:59

    Hi there,

    LOVE your script, thanks for much! I was having an issue with the orientation change. For some reason when I switch to landscape, the window seems to stretch out and I can only see the top-left corner; refreshing it doesn’t help either. If I load the page in landscape then it works fine; I’m so confused :S lol..Any idea why that might be happening?

      • Author: Anuj
      • Posted on: 2010/08/05
      • At: 18:21

      Nevermind – got it >_< ..thanks for an amazing script!

    • Author: john
    • Posted on: 2010/08/07
    • At: 12:10

    There is a problem when the height of the content is too big. The performance greatly reduces and then all pages afterwards are displayed with lower resolution (iphone 4)

    • How big is “too big”? Anyway, that seems a hardware limit, I’m afraid there’s very little we can do about it.

    • Author: Basti
    • Posted on: 2010/08/09
    • At: 11:14

    At version 3.5 there are still no select boxes clickable…Does anyone know a solution for this?

    “v3.5 also fixes a nasty bug with scrollbars and multiple iScroll instances.”

    • Author: Conor
    • Posted on: 2010/08/09
    • At: 18:53

    Hi Matteo, great script! I’m having one small issue though and was hoping you could help shed some light.

    It seems that once I set up an iScroll element, I lose the default behaviour for link tags on my iPad ( i.e. touching an anchor tag will show a light grey hit-area box ).

    Is there any way to get this behaviour back from within an iScroll element?

    • in index.html, line 31, replace “touchstart” with “touchmove”.

    • Author: Markku
    • Posted on: 2010/08/10
    • At: 07:56

    Hi,
    As so many others have already said here, just great job, Matteo! I got it work right away…
    I have one question in my mind. Is it possible to scroll elements on a page both vertically and horizontally so that only those elements are scrolled vertically which are visible on the screen? Hopefully you understand what I mean? I will try this but maybe it’s better to ask first from you.

    • Author: Chris
    • Posted on: 2010/08/10
    • At: 20:44

    Hello,

    I can’t seem to be able to use a jQuery click function with items in the footer. It’s only recognizing ontouchend events. Anyway to fix this?

    • Author: tim romano
    • Posted on: 2010/08/11
    • At: 15:22

    Matteo, nice work. I’ve now got two separate vertically scrolling regions to be happy on my page, with iScroll. I permit the user to change text size; they can can pinch elsewhere on the page, outside of these regions, to change font size. The vertical scrolling still works after a font-size change using expand-pinch.

    A feature request: it is possible to distinguish between swipe and pinch, I think, by counting the touches:

    pinching = (event.touches.length > 1);

    That is a rather crude way but it works (except for two-fingered swipes).

    Would it then be possible to invoke preventDefault in touchmove only when the user is swiping, not pinching, in the following manner?

    if (swiping==true && pinching==false) event.preventDefault();

    I think this would allow the user to change text size by pinching inside the scrolling region.

    • you may try with if (event.touches.length > 1) { return; } that will skip the iscroll all together

    • Author: Aru
    • Posted on: 2010/08/12
    • At: 06:06

    Hi Matteo, that’s great!

    But, I have a problem with the script, I can’t make my list scrolling.
    I define an absolute position with defined width in my div

    this is my html :

    Lavenderx 5
    Tulipx 2
    Lilyx 1
    Rosex 3
    Lavenderx 5
    Tulipx 2
    Lilyx 1
    Rosex 3
    and css :

    .content.plants{
    display: block;
    background: transparent url(../images/bg_board.png) repeat;
    padding-left: 5px;
    padding-right: 5px;
    padding-bottom: 5px;
    padding-top: 5px;
    background-color: #FDE6C2;
    -moz-border-radius-bottomright:10px; /* radius for firefox */
    -moz-border-radius-topright:10px; /* radius for firefox */
    -moz-border-radius-bottomleft:10px; /* radius for firefox */
    -webkit-border-top-right-radius:10px; /* radius for safari, chrome, etc */
    -webkit-border-bottom-right-radius:10px; /* radius for safari, chrome, etc */
    -webkit-border-bottom-left-radius:10px; /* radius for safari, chrome, etc */
    height: 210px;
    }
    .content.plants.list{
    display: block;
    background-color: #FDE6C2;
    background-image: none;
    height: 200px;
    overflow: hidden;
    }

    #for_scroll{
    overflow: hidden;
    }

    .content.plants.list li{
    margin: 10px 5px 10px 5px;
    }

    .left_span{
    margin-left:20px;
    margin-top:5px;
    float: left;
    /*display: inherit;*/
    }

    .right_span{
    margin-right:20px;
    margin-top:5px;
    float: right;
    /*display: inherit;*/
    }

    .menu.contents.item{
    background: transparent url(../images/btn_long.png) no-repeat;
    width: 213px;
    height: 25px;
    display: inline-block;
    vertical-align:top;
    cursor: pointer;
    color: white;
    font-size: 15px;
    font-weight: bold;
    }

    I’m sorry my comment got so long

    • Author: Claudio Cicali
    • Posted on: 2010/08/12
    • At: 17:47

    Ciao Matteo,

    I probably stumbled upon another “form field” problem here but, I’d like to ask you anyway. I’m quite new on developing on touch devices, so the problem could not be strictly related to iScroll… anyway: I’ve some [a]s in the iScroll area, that when clicked should show up an input form field (outside the iScroll area) and focus it. This will pop up the keyboard as well. The problem is that when I activate iScroll on some area, the field shows up but the focus is not being given to it (and the keyboard does not pop up…). Everything works fine if iScroll is not activated though. I’m on a iPad… any help would be greatly appreciated.

    • you may try by giving focus + dispatching a fake click to the field.

      • Author: Claudio Cicali
      • Posted on: 2010/08/12
      • At: 18:34

      Matteo, reading through your code, it seems everything is all right… you rightly “fake” a click and a focus on the touched element (my “a”). And my click callback is called… but for some reason, the focus() I call from inside the callback is simply not fired… I’ve tried to setTimeout the focus(), try/catch blocks… nothing :)

      Thank you anyway!

      • Author: Claudio Cicali
      • Posted on: 2010/08/13
      • At: 11:09

      I’ve reduced the problem at its very minimum… see http://paste2.org/p/948660 (to bypass that, I need to edit iScroll so that on “touchStart()” of A elements it will NOT preventDefault)

    • thanks for the heads-up, Claudio.

    • Author: Anuj
    • Posted on: 2010/08/12
    • At: 18:08

    Hm..for some reason textboxes in Android cannot be tapped and focussed on with iScroll. Has anyone had the same problem or am I doing something wrong here?

      • Author: John
      • Posted on: 2010/08/17
      • At: 04:03

      I am experiencing this too. I cannot tap on text input to bring up the virtual keyboard.

      It works great in iPhone though.

    • Author: Eric
    • Posted on: 2010/08/12
    • At: 20:44

    Hi,
    I am trying to incorporate iScroll into a GWT/Ext-GWT application. Does anybody have any hints and/or tricks that could help me?

    Basically I have a panel object which contains a treegrid component. I need to be able to have the treegrid component scroll when there is too much data. I’ve been struggling with lots of different options but can’t seem to get it.

    Can anyone offer some advice?

    • Author: ToM
    • Posted on: 2010/08/13
    • At: 10:45

    Hi, at the moment I´m working on an webapp for ipad and iphone.
    The scrolling works really nice, but I got one problem with the html 5 video-tag.

    The video stays at its place and doesn´t scroll. The rest in the div scrolls.

    Any ideas on how to fix it.

    Greetings,

    ToM

    • Author: netthales
    • Posted on: 2010/08/13
    • At: 17:38

    Hi Matteo,
    really great script! I was fighting quite a few hours with my scrollable divs on the iPad, before I finally found iScroll. Unfortunately, this script is just half the way to reanimate my table view in the iPad. To check it out, click on my username “netthales”. Do you guys have any suggestion, how I could translate my script to iScroll, easily?

    • Author: kaskooye
    • Posted on: 2010/08/13
    • At: 20:34

    Ciao Matteo,

    You were recently tallking about iScroll happy users, and backlinking :)

    So, here’s my contribution to the common effort !

    This in now very preliminary alpha work, but may evolve upon my free time.

    http://kaskooye.over-blog.com/

    Kindly regards,
    Jean-Philippe

    • Author: Phreemann
    • Posted on: 2010/08/13
    • At: 20:43

    Hi Matteo,

    Firstly, thanks for an excellent script. I’ve got it set up and working perfectly in Android 2.0+, but I was wondering if you could advise on a problem I’m having with Android 1.6.

    Basically, I’ve got a lot of scrollable content which takes more than one swipe to scroll from top to bottom. This is no problem in Android 2.0+, but in Android 1.6 the second touch causes issues. When trying to scroll for the second time, the scrollable content jumps back to the top, and also seems to jump to the left outside the boundaries of the wrapper.

    It’s very strange – have you any suggestions as to what I might have done wrong? Basic setup below, I’m using jQuery to update the content in the scroller div, waiting for the content to load and then refreshing the iScroll.

    Many thanks. =)

    CSS:
    #wrapper { float: left; background: url(../images/bg.png) repeat; width: 91.66%; padding: 4.17%; position: relative; z-index: 1; overflow: hidden; height: 0px; }
    #scroller { float: left; width: 100%; height: auto; }

    HTML:

     

    JS:
    function updateContent() {
    var pageHeight = screen.availHeight;
    document.getElementById(‘wrapper’).style.height = (pageHeight * 0.8) + ‘px’;
    var content = getContent(pageID);
    document.getElementById(‘scroller’).innerHTML = content;
    document.addEventListener(‘touchmove’, function(e){ e.preventDefault(); });
    myScroll = new iScroll(‘scroller’, { hScrollbar: false, vScrollbar: true, bounce: true, checkDOMChanges: false, scrollbarClass: ‘scrollbar’, fadeScrollbar: true, momentum: true, shrinkScrollbar: true, desktopCompatibility: false });
    };

    window.onload = updateContent();
    setTimeout(function () { myScroll.refresh(); }, 1000);