Current scroll position when using -webkit-overflow-scrolling:touch – Safari iOS javascript event (scrollTop / scrollLeft)

I’m using -webkit-overflow-scrolling:touch to make a div with overflow:scroll; scroll smoothly through iOS touch events.

It works brilliantly, except it doesn’t seem to update element.scrollTop or element.scrollLeft while it’s scrolling. It only updates element.scrollTop / triggers a scroll event when the momentum runs out and it stops.

  • Google Maps Javascript API Doesn't Respond to Touch Events in iOS 10
  • How to capture “Clear” event on input type date for IOS native date picker
  • Best method to determine if viewport or 'standard' browser
  • Want an iPhone / iPad / iOS Webpage that is 100% width/height
  • Is there an alternate way to trigger autocorrect/autocomplete on mobile Safari (on iOS) when the user presses enter?
  • Accessing localStorage when home button is pressed in Phonegap/iOS
  • Does anyone know of a way of finding out its current scroll position and if there’s an event I can listen for? I wondered if it can be found through a CSS3 property perhaps? Thanks

    Example below showing two attempts:

    <!DOCTYPE html>
    <body>
        <div id="display_a">Scroll is: 0</div>
        <div id="display_b">Scroll is: 0</div>  
        <div id="element" style="width:800px;overflow-x:scroll;-webkit-overflow-scrolling:touch;">
            <div style="font-size:100px;width:1850px;">
                a b c d e f g h i j k l m n o p q r s t u v w x y z
            </div>
        </div>
        <script>
            var e = document.getElementById("element");
            var display_a = document.getElementById("display_a");
            var display_b = document.getElementById("display_b");
            e.addEventListener("scroll",function(event){display_a.innerHTML = "Scroll is: " + event.target.scrollLeft;});
            setInterval(function(){display_b.innerHTML = "Scroll is: " +  e.scrollLeft;},100);
        </script>   
    </body>
    </html>
    

    ============ UPDATE ============

    iOS 8 has sorted this behaviour. Scroll events are now triggered while scrolling.

    Note that you’ll now have to deal with negative scroll values during the bounce scroll.

  • console.time() on iOS Safari
  • Assets not found by Cordova/Phonegap
  • shiftKey in Safari on iOS
  • Iphone UIWebView not working on javascript buttons
  • open app with custom scheme - prevent “open in <appname>” warning?
  • Why does Javascript pause when long pressing on an Android or iOS device?
  • 7 Solutions collect form web for “Current scroll position when using -webkit-overflow-scrolling:touch – Safari iOS javascript event (scrollTop / scrollLeft)”

    In the iOS Developer Library, there is an explanation in the Safari guidelines about it:

    http://developer.apple.com/library/IOs/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html

    Basically, the event flow for the scrolling goes like this:
    touch/start dragging(mousewheel event)-> pan/movement(no events) -> stop(onscroll)

    So there is nothing like a continuous event of scrolling being triggered while the pan happens there just an onScroll at the end of the gesture.

    If you find an optional way to accomplish that, let me know 🙂

    In a similar situation I am using scrollability.js, which does a really nice job simulating the native scrolling behavior. I’m then listening for the ‘scrollability-start’ event and monitoring the top/left attributes of the scrolled element. I know it’s not ideal, but it’s a decent alternative.

    This might help. It’s a jQuery solution that I’m using to force pagination on IOS side-to-side swipes. It’s not exactly the same case as you’re working. I’m using the “overflow-scrolling:auto” which does not behave like the “touch” version.

    #yourDiv {
        -webkit-overflow-scrolling: auto;
        overflow:auto;
    }
    

    I use “overflow-scrolling:auto” because it reacts quicker to the touchend event. Unfortunatley, “overflow-scrolling:touch” does indeed seem to resist javascript and CSS animation while it’s in motion. But at least you can get some location information out of it during the scroll.

    var pageSwiping = false;
    
    $('#yourDiv').on('scroll', function(e) {
        if (pageSwiping !== true  ) {
            pageSwiping = true;
            var offset = $('#'+e.target.id).scrollLeft();
            $('#yourDiv').one( 'touchend',{elem:e.target.id,dragStart:offset},divMove);
        };
    });
    
    var divMove = function(e) {
        pageSwiping = false;
        var elem = e.data.elem;
        var dragEnd = $('#'+elem).scrollLeft();
        var dragDelta = (dragEnd - e.data.dragStart)
            // Make page-alignment decisions based on dragDelta
    };
    

    Here is my repository where I’ve added the callback onScrolling() to let me know when the momentum scrolling animation is occurring in animate(): https://github.com/simpleshadow/iscroll/blob/master/src/iscroll.js

    I’ve made an example app using his suggestion here: http://jsfiddle.net/simpleshadow/wQQEM/22/

    @robertlawson86 on Github made this suggestion to help provide an idea on when to grab the position during momentum scrolling. See example and discussion: https://github.com/cubiq/iscroll/issues/183

    I know is weird, but you can keep track of scrollLeft/scrollTop just by registering touchstart event:

    e.addEventListener("touchstart",function(event){});
    

    Get the position of a horizontal scroller while srolling ( via css overflow-y:scroll )

    $('#myNode').bind('scroll', function(e){
      var myPos = e.target.scrollLeft;
      // do something with myPos but don't naughty
    })
    

    If it helps, scrollTop and scrollLeft are updated in real-time within the touchmove event handler:

    $(function()
    {
        var $div = $("#scroll")
        var $p   = $("#display");
    
        var update = function(e)
        {
            $p.text( e.type +": "+ $div.scrollLeft() +", "+ $div.scrollTop() );
        }
    
        $div.bind( "touchmove", update )
            .bind( "scroll",    update );
    });