web-dev-qa-db-fra.com

Mobile Safari bug sur le bouton positionné fixe après scrollTop modifié par programme ...?

Je suis sur le point de faire une page Web mais il y a un bug dans Mobile Safari (iPhone et iPad iOS 5.0.1) avec deux boutons qui sont fixés dans les coins supérieur et inférieur droit ..

Les boutons ne sont fondus qu'après avoir cliqué sur Soumettre dans une zone de texte qui s'ouvre au reste de la page ... Une fois le reste de la page chargé et les boutons fondus, vous pouvez cliquer sur l'un d'eux et ils fonctionnent tous les deux ...

Cependant, cliquer dessus provoque un défilement programmatique et une fois ce défilement terminé, vous ne pouvez plus cliquer sur aucun des boutons jusqu'à ce que vous faites défiler physiquement la page avec votre doigt, même juste un tout petit défilement d'un pixel ...

Ce que j'ai remarqué, c'est qu'après le défilement programmatique, si vous appuyez juste légèrement en dessous du bouton TOP, vous voyez la surbrillance comme si vous appuyiez sur le bouton BOTTOM et l'action du bouton inférieur est traitée, ce qui me dit que le bogue est que lors du défilement par programmation, le bouton de position fixe se déplace toujours avec le reste de la page et ne revient pas à sa position fixe jusqu'à ce qu'un défilement tactile soit effectué ....

Est-ce que quelqu'un connaît un moyen de contourner cela ..?

J'ai ajouté une fenêtre contextuelle qui montre quel bouton a été pressé pour que vous puissiez le tester, rappelez-vous qu'après la première pression sur le bouton bas (qui fonctionne), essayez à nouveau d'appuyer, cela ne fonctionnera pas, mais cliquez juste en dessous du bouton haut et vous verrez les actions du bouton vers le bas se produire ....

http://www.tsdexter.com/ceos

merci pour l'aide.

Thomas

(également si vous pouvez m'indiquer où je peux soumettre un bogue à Apple ce serait bien aussi, à moins qu'un ne l'ait déjà été))

MODIFIER: il suffit de cliquer sur l'une des flèches de soumission, vous n'avez pas besoin d'entrer un salaire/salaire par défaut

EDIT 2: Voici un exemple plus simple pour montrer le même problème.

http://www.tsdexter.com/MobileSafariFixedPosBug.html

EDIT 3: Bug signalé à Apple

35
tsdexter

Je l'ai contourné en ajoutant un div élevé de 101% puis en le supprimant (presque) immédiatement.

Essayer:

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

et lorsque vous faites défiler:

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

Il fonctionne également avec jQuery.scrollTo.

Voir un exemple ici .

13
Chad Smith

Nous avons également rencontré ce bug sur 2 applications iPad différentes, pour nous, la meilleure solution était de supprimer temporairement la position fixe de l'élément fixe une fois le défilement animé terminé, puis d'utiliser window.scroll avec la valeur verticale que nous venions d'effectuer l'animation faites défiler jusqu'à, puis appliquez à nouveau le style de position fixe. Il provoque un blip très mineur car l'ipad restitue l'élément mais c'est préférable au bogue.

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" });
});
28
Dominic Warren

J'avais plusieurs liens sur des éléments fixes distincts (une fenêtre contextuelle modale + une division de blackout fixe + une barre d'outils fixe normale) et aucune de ces réponses ne fonctionnait, j'ai donc eu un bricolage pour essayer des variations sur le même thème. Comme tous ces éléments suggèrent que la clé consiste à obtenir un rendu des éléments.

Au départ, j'ai essayé d'ajouter 1px à la largeur des éléments fixes et de le supprimer. Cela a provoqué un nouveau rendu, mais les éléments restitués sont devenus mal alignés avec les éléments non restitués - un autre résultat de ce bogue iOS, je suppose. La réponse était simplement d'ajouter à la largeur du corps et de soustraire à nouveau (ou de régler sur auto), c'est-à-dire:

//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);

Si vous n'utilisez pas jquery, vous devrez obtenir la largeur actuelle du corps + 1px, puis définir la largeur.

7
Ed Kirk

Voici ma solution si comme moi, aucune des solutions précédentes ne fonctionne pour vous.

L'astuce est:

  • Faites votre défilement (Animate ou scrollTo, etc.)
  • Juste après votre défilement, positionnez: absoluez vos éléments fixes
  • Sur l'événement 'touchmove', restaurez la position: fixe

Voici un exemple:

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

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

J'ai utilisé la même astuce pour le pied de page collant et d'autres éléments fixes flottants.

4
Stephane Brillant

Une variante de cela a également fonctionné pour moi. Essayer de ne pas utiliser de frameworks où je peux sur 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);
3
httpete


Après avoir passé quelques heures à ce sujet, j'ai trouvé une solution de contournement: essayez de faire défiler (peut-être avec une animation) puis de faire défiler à nouveau au même point (sans animation).
De cette façon, vous forcez le navigateur à supprimer le mauvais rendu de la vue.

Exemple:

$('body, html')
    .animate({scrollTop: 0})
    .scrollTop(0);
2
Luca De Angelis

J'avais le même problème avec iOS5 et JQueryMobile. En-tête et pied de page fixes. Contenu extensible et tout à coup, j'avais un pied de page fantôme que vous pouviez voir mais pas toucher. J'ai eu un peu de mal à obtenir une position de changement droite à l'absolu puis à retourner au travail. Cela ne semblait fonctionner que de temps en temps. J'ai fini par utiliser ça.

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

Cela crée un "blip" provocant lorsque le pied de page fait son travail. Cependant, j'ai constaté que 98% du temps, le pied de page restait en bas de la page. Tous les autres contournements et ajustements que j'ai trouvés et essayés n'ont pas toujours laissé le pied de page en bas ou ils n'ont pas résolu le problème en premier lieu.

Espérons que Apple sera bientôt corrigé.

1
JDubDev

Exemple de 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'});
    });
}
0
ShibinRagh

Une autre variante d'une solution consiste à augmenter la taille de la largeur du document de 1 px, puis à l'annuler immédiatement. Cela a l'avantage de ne plus créer d'éléments et il n'y a aucun scintillement que j'ai connu.

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

0
mckamey

Au cas où cela pourrait aider quelqu'un:

J'ai eu exactement le même problème, et mon code ressemblait à ceci (c'est une webapp d'une seule page):

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

J'ai passé des heures à tout essayer (101% de diviseurs de hauteur, changer le type de position ...), mais finalement la dernière suggestion décrite sur Device-Bugs a sauvé la journée. Dans mon cas, il s'agissait simplement de faire défiler lorsque les divs ne sont pas rendus:

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

J'ai découvert le comportement exact que vous décrivez dans une application iPhone que j'écris. Je charge un tas de texte HTML avec un index sur le côté droit. Après avoir sélectionné un élément dans le menu et fait défiler le texte, le menu ne répondait plus (car la zone d'atterrissage avait défilé depuis le dessous). J'ai également vu que même un petit défilement du texte réactiverait le menu d'index.

J'ai créé un cas de test et téléchargé le fichier ici (si vous affichez ceci sur un navigateur non iPhone, réduisez la fenêtre verticalement pour voir le comportement correct):

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

J'ai compris que le menu d'index défilait avec le texte (même si le menu visible ne bougeait pas) après avoir appuyé sur B, puis à nouveau sur B. Au lieu de défiler jusqu'à B (ne bougeant pas), il a défilé jusqu'à D.

En ce moment, je suis coincé. J'espère pouvoir ajouter du code JavaScript (je n'ai jamais programmé en JavaScript, c'est donc un léger problème) qui fera défiler le texte d'un pixel après avoir levé le doigt d'un élément de menu (et après que le texte ait défilé à l'endroit choisi, bien sûr). Peut-être que JavaScript peut détecter le défilement, puis y ajouter un autre défilement.

0
Cliff Harris