Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webkit overflow scrolling touch CSS bug on iPad

Tags:

css

ios

webkit

ipad

If you visit this page on your iPad device on the latest version of iOS you can follow along.

http://fiddle.jshell.net/will/8VJ58/10/show/light/

I have two elements with the new -webkit-overflow-scrolling: touch; property and value applied. The left hand grey area has plenty of content and will scroll in portrait or landscape. The right will only scroll in landscape.

If you start in landscape (refresh in landscape) you can scroll both areas with the inertia scrolling. Works great. Now flip your iPad into portrait and only the left hand area will scroll. This is as intended. But when you flip back to landscape the right hand area will no longer scroll at all, whereas the left hand area is fine still.

It's obvious how to stop this happening, but I don't always have the content to fill the area.

So any ideas?

Thanks in advance,
Will :)

like image 742
will Avatar asked Jan 31 '12 17:01

will


4 Answers

Coming late with a similar, but simpler solution.

var $el = $('.myElementClass');

function setOverflow(){
    $el.css({webkitOverflowScrolling: 'touch', overflow: 'auto'});
}

function resizeHandler(){
    $el.css({webkitOverflowScrolling: 'auto', overflow: 'hidden'});
    setTimeout(setOverflow,10);
}

[EDIT] Watch out, after experimenting (a lot), I found out that display:none declarations will surely break the webkit-overflow-scrolling: touch feature. Never use it on elements (or parents of elements) that are supposed to support touch scrolling.

like image 95
Armel Larcier Avatar answered Nov 07 '22 04:11

Armel Larcier


I am actually having the exact same issue. I have narrowed it down to the fact that it affects DIVs whose content's no longer require scrolling when the orientation is changed.

In your example. The DIV on the right scrolls in landscape, does not NEED to scroll in portrait, but then needs to scroll again. I have tested this when both DIVs (left and right) need to scroll regardless of orientation and its not a problem.

UPDATE:

I actually seem to have fixed this!

The issue appears to be a timing issue. During resize the inner content is not big enough to warrant scrolling on the outer DIV that has overflow. After wasting a day on this, I finally came up with this hack:

<div id="header" style="position:fixed; height:100px">Header</div>
<div id="content" style="overflow: auto; -webkit-overflow-scrolling: touch">
   <div id="contentInner">
      content that is not long enough to always scroll during different orientations
   </div>
</div>

Here is my logic whenever the page resizes:

   function handleResize()
    {
        var iHeight = $(window).height() - $("#header").height();

        // Height needs to be set, to allow for scrolling - 
        //this is the fixed container that will scroll
        $('#content').height(iHeight - 10);

        // Temporarily blow out the inner content, to FORCE ipad to scroll during resizing
        // This is a timing issue where the inner content is not big enough during resize post orientation to require the outer DIV to scroll
        $('#contentInner').height(1000);

        // Set the heights back to something normal
        // We have to "pause" long enough for the re-orientation resize to finish
        window.setTimeout(delayFix, 10);
}

function delayFix()
{
    var iHeight = $(window).height() - $("#header").height();

    // Inner divs force the outer div to always have at least something to scroll.  This makes the inner DIV always "rubber-band" and prevents
    // the page from scrolling all over the place for no reason.
    // The height of the inner guy needs to be AT LEAST as big as the container and actually a nip bigger to cause the
    // scrollable area to 'rubber band' properly
    $('#contentInner').height(iHeight + 20);

}
like image 15
ProVega Avatar answered Nov 07 '22 02:11

ProVega


I was able to use a known "fix" to force an iOS6 redraw to correct this issue without having to use setTimeout.

$(window).on('orientationchange', function()
{
    var $elem=$('[selector]');
    var orgDisplay=$elem.css('display');
    $elem.css('display','none');
    $elem.get(0).offsetHeight;
    $elem.css('display',orgDisplay);
});
like image 4
user2397538 Avatar answered Nov 07 '22 02:11

user2397538


I experienced the same bug on iPhone, iPod and iPad. This is not restricted to the latter only.

I tried everything that was suggested to be a solution, but eventually the sweet combination ended up being detaching the element, appending it to its container and explicitly assigning it its own height while doing this, like so:

$(window).on('orientationchange', function(){
  var el  = $('.troublemaker').detach(),
      elh = el.height();
  setTimeout( el.css({'height':elh+'px'}).appendTo('.container'), 50 );
});
like image 2
2C-B Avatar answered Nov 07 '22 04:11

2C-B