Mobile Safari bug on fixed positioned button after scrollTop programmatically changed…?

核能气质少年 提交于 2019-11-26 21:41:17

I got around it by adding a 101% high div then (almost) immediately removing it.

Try:

<style>
.iosfix {
  height: 101%;
  overflow: hidden;
}
</style>

and when you scroll:

window.scrollTo(0, _NEW_SCROLLTOP_);
$('body').append($('<div></div>').addClass('iosfix'));
setTimeout(function() {
  $('.iosfix').remove();
}, 500);

It also works with jQuery.scrollTo.

See an example here.

We also encountered this bug on 2 different iPad applications, for us the best fix was to temporarily remove the fixed position from the fixed element once the animated scroll had finished, then use window.scroll with the vertical value we’d just performed the animated scroll to, then finally re-apply the position fixed style. It does cause a very minor blip as the ipad re-renders the element but its preferable to the bug.

var $fixedElement = $('#fixedNavigation');
var topScrollTarget = 300;
$("html:not(:animated),body:not(:animated)").stop().animate({ scrollTop: topScrollTarget }, 500, "swing", function(evt) {
    $fixedElement.css({ "position": "relative" });
    window.scroll(0, topScrollTarget );
    $fixedElement.css({ "position": "fixed" });
});

I had multiple links on separate fixed elements (a modal popup + fixed blackout div + normal fixed toolbar) and none of these answers were working so I had a tinker about trying variations on the same theme. Like all these suggest the key is getting elements re-rendered.

Initially I tried adding 1px to the width of fixed elements and removing it. This did cause re-rendering, but re-rendered elements became mis-aligned with non re-rendered elements - another result of this iOS bug I suspect. The answer was to simply add to the width of the body and subtract again (or set to auto), ie:

//jQuery will calculate the current width and then +1 to this and set it
$('body').css('width', '+=1');

//Remove width css
setTimeout(function() {
  $('body').css('width', '');
}, 1);

If not using jquery you will need to get the current width of body +1px to it and then set the width.

Here is my solution if like me, none of the previous solution is working for you.

The trick is:

  • Do your scroll (Animate or scrollTo, etc.)
  • Just after your scroll, position:absolute your fixed elements
  • On the 'touchmove' event, restore the position:fixed

Here an example:

  $('body').animate({
       scrollTop: newPos}, 1000, 'jswing', function () {
          $('header').css({position:'absolute', top:newPos});
  });

  $(document).bind('touchmove',function(){
       $('header').css({position:'fixed', top:'0px'});
  });   

I used the same trick for sticky footer and other floating fixed elements.

httpete

A variation of this worked for me as well. Trying to not use frameworks where I can on mobile.

    var d = document.createElement("div");
    d.style.height = "101%";
    d.style.overflow = "hidden";
    document.body.appendChild(d);
    window.scrollTo(0, scrollToM);
    setTimeout(function() {
        d.parentNode.removeChild(d);
    }, 10);
Luca De Angelis


After spending a couple of hours on this, I found a workaround: try scrolling (maybe with an animation) and then scrolling again to the same point (without animation).
This way you force the browser to delete the wrong rendering from the view.

Example:

$('body, html')
    .animate({scrollTop: 0})
    .scrollTop(0);

I was having the same problem with iOS5 and JQueryMobile. Fixed Header & Footer. Expandable content and suddenly i had a ghost footer that you could see but not touch. I had a bit of a problem getting a straight change position to absolute then back to work. It seemed to only work some of the time. I ended up using this.

        $(myFixedFooter).css("position", "relative").hide(0, function () {
            $(this).show(0).css("position", "");
        });

This defiantly creates a "blip" as the footer does its thing. Hoever i found that some 98% of the time the footer stayed at the bottom of the page. All the other work arounds and tweaks i found and tried didn't always leave the footer at the bottom or they didn't solve the problem in the first place.

Hopefully Apple will fix soon.

I discovered the exact behavior you describe in an iPhone app I'm writing. I load a bunch of HTML text with an index on the right side. After selecting an item from the menu and scrolling the text, the menu would then become unresponsive (because the landing zone had scrolled out from under it). I also saw that even a tiny scroll of the text would reenable the index menu.

I created a test case and uploaded the file here (If you view this on a non-iPhone browser, make the window small vertically to see the correct behavior):

http://www.misterpeachy.com/index_test.html

I figured out that the index menu was scrolling with the text (even though the visible menu didn't move) after I tapped B and then tapped B again. Instead of scrolling to B (basically not moving), it scrolled to D.

Right now I'm stuck. I'm hoping that I can add some JavaScript code (I've never programmed in JavaScript, so that is a slight problem) that will scroll the text one pixel after I lift my finger off a menu item (and after the text has scrolled to the selected place, of course). Maybe JavaScript can detect the scroll and then add another scroll to that.

In case it can help someone:

I had the exact same problem, and my code looked something like this (it's a single-page webapp):

window.scrollTo(0,0);
$('section.current').removeClass('current');
$(target).addClass('current');

I spent hours trying everything (101% height divs, changing the position type...), but finally the last suggestion described on Device-Bugs saved the day. In my case it was just a matter of scrolling when the divs aren't rendered:

$('section.current').removeClass('current');
window.scrollTo(0,0);
$(target).addClass('current');
mckamey

Another variation of a solution is to increase the size of the document width by 1px and then immediately undo it. This has the advantage of not creating any more elements and there isn't any flicker that I've experienced.

https://stackoverflow.com/a/11479118/43217

Example code

if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
    $(document).on('focus', 'input, textarea', function() {
        $('header').css({'position':'static'});
    });
    $(document).on('blur', 'input, textarea', function() {
        $('header').css({'position':'fixed'});
    });
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!