Positionnement fixe et clavier virtuel iOS 5

138

J'ai un site Web mobile qui a un div épinglé au bas de l'écran via position: fixed. Tout fonctionne bien dans iOS 5 (je teste sur un iPod Touch) jusqu'à ce que je sois sur une page avec un formulaire. Lorsque je tape dans un champ de saisie et que le clavier virtuel apparaît, soudainement la position fixe de mon div est perdue. Le div défile maintenant avec la page tant que le clavier est visible. Une fois que j'ai cliqué sur Terminé pour fermer le clavier, le div revient à sa position en bas de l'écran et obéit à la position: règle fixe.

Quelqu'un d'autre a-t-il vécu ce genre de comportement? Est-ce prévu? Merci.

Jeffc
la source
Oui, il semble qu'Apple n'ait pas si bien pensé à celui-ci pour IOS5. Tout élément de position fixe devient relatif à la page dès que le clavier virtuel apparaît. Ce serait probablement OK si les éléments revenaient à une position absolue car cela ne casserait pas la mise en page. Malheureusement, le placement réel de ces éléments est beaucoup moins prévisible. J'ai exactement ce problème avec mon en-tête fixe sur [SUPPRIMÉ]. Faites défiler la page, puis cliquez sur le champ de recherche et bang ... mise en page cassée. J'ai même essayé de résoudre ce problème en revenant au positionnement absolu sur l'événement de mise au point, ce qui fonctionne mais ensuite je los
John williams
2
J'ai rencontré ce même problème. Quelqu'un a-t-il signalé un bogue à Apple pour voir comment résoudre ce problème? De plus, quelqu'un d'autre a-t-il vu ce comportement se poursuivre dans iOS6?
Robert Hui
1
Je rencontre le même problème avec iOS6.
Redtopia
24
Le même problème semble toujours exister dans iOS7!
Ria Weyprecht
5
Ne semble pas être corrigé dans iOS 8 ...
contactmatt

Réponses:

49

J'ai eu ce problème dans mon application. Voici comment j'y travaille:

input.on('focus', function(){
    header.css({position:'absolute'});
});
input.on('blur', function(){
    header.css({position:'fixed'});
});

Je fais simplement défiler vers le haut et je le positionne là-bas, de sorte que l'utilisateur iOS ne remarque rien d'étrange. Enveloppez ceci dans une détection d'agent utilisateur afin que les autres utilisateurs n'obtiennent pas ce comportement.

Nick Retallack
la source
Je suis littéralement tombé sur ce problème aujourd'hui et cela semblait le plus raisonnable, +1.
Daniel
3
Cela fonctionne plutôt bien. Je n'appelle cela que pour les appareils iOS: var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
Redtopia
8
J'ai également supprimé $ (window) .scrollTop (0) ... Je ne pense pas que ce soit nécessaire et cela a provoqué un défilement indésirable.
Redtopia
1
Ou simplement document.body.scrollTop = 0si vous n'utilisez pas jQuery et ciblez les derniers navigateurs.
Langdon
Sur les formulaires plus longs, le réglage de $(window).scrollTop(0);peut entraîner le déplacement de l'entrée focalisée hors de l'écran, par exemple une entrée plus bas dans la page, ou si un iPhone est en mode portrait. Une meilleure solution est la mise au point header.css({position:'absolute',top:window.pageYOffset+'px'});et le jeu de flou header.css({position:'fixed',top:0});.
robocat
16

J'ai eu un problème d'ipad légèrement différent où le clavier virtuel poussait ma fenêtre hors écran. Ensuite, après que l'utilisateur ait fermé le clavier virtuel, ma fenêtre était toujours hors écran. Dans mon cas, j'ai fait quelque chose comme ce qui suit:

var el = document.getElementById('someInputElement');
function blurInput() {
    window.scrollTo(0, 0);
}
el.addEventListener('blur', blurInput, false);
ds111
la source
3
Ça ne m'aide pas :(
Dmitry
@Altaveron. Désolé d'entendre ça. C'était pour un problème spécifique que j'avais sur les appareils ios6 et inférieurs. Je n'ai pas revisité depuis.
ds111
14

C'est le code que nous utilisons pour résoudre le problème avec l'ipad. Il détecte essentiellement les écarts entre le décalage et la position de défilement - ce qui signifie que `` fixe '' ne fonctionne pas correctement.

$(window).bind('scroll', function () {
    var $nav = $(".navbar")
    var scrollTop = $(window).scrollTop();
    var offsetTop = $nav.offset().top;

    if (Math.abs(scrollTop - offsetTop) > 1) {
        $nav.css('position', 'absolute');
        setTimeout(function(){
            $nav.css('position', 'fixed');
        }, 1);
    }
});
la trappe
la source
Il vient du plugin jquery.timers. Vous pouvez utiliser window.setTimeout à la place.
Hatch le
le déclenchement de cette même fonction sur le flou d'entrée et la mise au point aidera également.
Blowsie
Genius - vraiment creuser ça. +1 à la suggestion de @ Blowsie d'utiliser la mise au point et le flou au lieu du défilement.
Skone
12

Les éléments à position fixe ne mettent tout simplement pas à jour leur position lorsque le clavier est relevé. J'ai trouvé qu'en incitant Safari à penser que la page avait été redimensionnée, les éléments se repositionneraient. Ce n'est pas parfait, mais au moins, vous n'avez pas à vous soucier de passer en «position: absolue» et de suivre vous-même les changements.

Le code suivant écoute simplement le moment où l'utilisateur est susceptible d'utiliser le clavier (en raison d'une entrée focalisée), et jusqu'à ce qu'il entende un flou, il écoute simplement les événements de défilement, puis effectue l'astuce de redimensionnement. Cela semble fonctionner assez bien pour moi jusqu'à présent.

    var needsScrollUpdate = false;
    $(document).scroll(function(){
        if(needsScrollUpdate) {
            setTimeout(function() {
                $("body").css("height", "+=1").css("height", "-=1");
            }, 0);
        }
    });
    $("input, textarea").live("focus", function(e) {
        needsScrollUpdate = true;
    });

    $("input, textarea").live("blur", function(e) {
        needsScrollUpdate = false;
    });
Riley Dutton
la source
Cela n'a pas fonctionné pour moi sur l'iPad. J'ai fini par changer la position du pied de page fixe en relative et avoir le pied de page en bas de la page jusqu'à ce que l'événement de flou d'entrée soit détecté lorsque j'ai changé la position sur fixe.
Akrikos
6
Ne fonctionne plus, iOS a probablement corrigé le bogue qui faisait fonctionner ce problème
Kevin
6

Juste au cas où quelqu'un tomberait sur ce fil, comme je l'ai fait lors de mes recherches sur ce problème. J'ai trouvé ce fil utile pour stimuler ma réflexion sur cette question.

C'était ma solution pour cela sur un projet récent. Il vous suffit de changer la valeur de "targetElem" en un sélecteur jQuery qui représente votre en-tête.

if(navigator.userAgent.match(/iPad/i) != null){

var iOSKeyboardFix = {
      targetElem: $('#fooSelector'),
      init: (function(){
        $("input, textarea").on("focus", function() {
          iOSKeyboardFix.bind();
        });
      })(),

      bind: function(){
            $(document).on('scroll', iOSKeyboardFix.react);  
                 iOSKeyboardFix.react();      
      },

      react: function(){

              var offsetX  = iOSKeyboardFix.targetElem.offset().top;
              var scrollX = $(window).scrollTop();
              var changeX = offsetX - scrollX; 

              iOSKeyboardFix.targetElem.css({'position': 'fixed', 'top' : '-'+changeX+'px'});

              $('input, textarea').on('blur', iOSKeyboardFix.undo);

              $(document).on('touchstart', iOSKeyboardFix.undo);
      },

      undo: function(){

          iOSKeyboardFix.targetElem.removeAttr('style');
          document.activeElement.blur();
          $(document).off('scroll',iOSKeyboardFix.react);
          $(document).off('touchstart', iOSKeyboardFix.undo);
          $('input, textarea').off('blur', iOSKeyboardFix.undo);
      }
};

};

Il y a un peu de retard dans la mise en place du correctif car iOS arrête la manipulation du DOM pendant le défilement, mais cela fait l'affaire ...

Jory Cunningham
la source
Cela fonctionne très bien jusqu'à iOS 7. Quelqu'un d'autre a des problèmes avec l'élément correctement positionné mais qui disparaît?
Rona Kilmer
@RonaKilmer Transformez le initen une fonction normale (pas d'auto-appel; il se déclenche trop tôt). Puis appelez iOSKeyboardFix.init();juste avant la fin de l' ifinstruction.
cfree
@cfree Merci, j'ai implémenté cela il y a quelque temps, mais ce n'est pas mon problème. Il se passe autre chose. Un de mes éléments fixes disparaît lorsqu'il est repositionné. L'autre non. Je ne peux pas blâmer cela sur la correction du clavier car cela ne se produit pas partout. Je n'ai pas vu que quelqu'un d'autre ait le même problème non plus, alors je vais devoir creuser plus profondément.
Rona Kilmer
4

Aucune des autres réponses que j'ai trouvées pour ce bogue n'a fonctionné pour moi. J'ai pu résoudre ce problème simplement en faisant défiler la page de 34 pixels, le montant du safari mobile le faisant défiler vers le bas. avec jquery:

$('.search-form').on('focusin', function(){
    $(window).scrollTop($(window).scrollTop() + 34);
});

Cela prendra évidemment effet dans tous les navigateurs, mais cela l'empêche de se briser dans iOS.

NealJMD
la source
4

Ce problème est vraiment ennuyeux.

J'ai combiné certaines des techniques mentionnées ci-dessus et j'ai trouvé ceci:

$(document).on('focus', 'input, textarea', function() {
    $('.YOUR-FIXED-DIV').css('position', 'static');
});

$(document).on('blur', 'input, textarea', function() {
    setTimeout(function() {
        $('.YOUR-FIXED-DIV').css('position', 'fixed');
        $('body').css('height', '+=1').css('height', '-=1');
    }, 100);
});

J'ai deux barres de navigation fixes (en-tête et pied de page, en utilisant le bootstrap de Twitter). Les deux ont agi bizarrement lorsque le clavier est en haut et à nouveau bizarre après que le clavier est en bas.

Avec ce correctif chronométré / retardé, cela fonctionne. Je trouve encore un problème de temps en temps, mais il semble être assez bon pour le montrer au client.

Faites-moi savoir si cela fonctionne pour vous. Sinon, nous pourrions trouver autre chose. Merci.

chat échappé
la source
2
Vous ne semblez pas avoir besoin de ce délai (au moins cela fonctionnait bien pour moi sans), et si cela se produit également sur certains éléments, à part cela, cette solution fonctionne très bien.
Phillip Gooch
3

Je rencontrais le même problème avec iOS7. Les éléments fixes inférieurs gâcheraient ma vue ne pas se concentrer correctement.

Tout a commencé à fonctionner lorsque j'ai ajouté cette balise meta à mon html.

<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,height=device-height" >

La partie qui a fait la différence était:

height=device-height

J'espère que cela aide quelqu'un.

pasevin
la source
Merci @pasevin. Cela a résolu mon problème dans iOS 9.3.2
stillatmylinux
3

J'ai pris la Jory Cunninghamréponse et je l'ai améliorée:

Dans de nombreux cas, ce n'est pas seulement un élément qui devient fou, mais plusieurs éléments positionnés fixes, donc dans ce cas, targetElemdevrait être un objet jQuery qui a tous les éléments fixes que vous souhaitez "corriger". Ho, cela semble faire disparaître le clavier iOS si vous faites défiler ...

Inutile de mentionner que vous devriez l'utiliser APRÈSDOM ready événement de document ou juste avant la </body>balise de fermeture .

(function(){
    var targetElem = $('.fixedElement'), // or more than one
        $doc       = $(document),
        offsetY, scrollY, changeY;

    if( !targetElem.length || !navigator.userAgent.match(/iPhone|iPad|iPod/i) )
        return;

    $doc.on('focus.iOSKeyboardFix', 'input, textarea, [contenteditable]', bind);

    function bind(){
        $(window).on('scroll.iOSKeyboardFix', react);
        react();
    }

    function react(){
        offsetY = targetElem.offset().top;
        scrollY = $(window).scrollTop();
        changeY = offsetY - scrollY;

        targetElem.css({'top':'-'+ changeY +'px'});

        // Instead of the above, I personally just do:
        // targetElem.css('opacity', 0);

        $doc.on('blur.iOSKeyboardFix', 'input, textarea, [contenteditable]', unbind)
            .on('touchend.iOSKeyboardFix', unbind);
    }

    function unbind(){
        targetElem.removeAttr('style');
        document.activeElement.blur();

        $(window).off('scroll.iOSKeyboardFix');
        $doc.off('touchend.iOSKeyboardFix blur.iOSKeyboardFix');
    }
})();
vsync
la source
2
@vsync excuses, je ne savais pas que vous étiez un `` chef cuisinier ''
Mike
lors de la sélection, le focus d'entrée dans cet en-tête de temps se déplace vers le haut (non visible) .Je souhaite fixer le div d'en-tête lors de la mise au point des fichiers de sélection et d'entrée. n'importe qui s'il vous plaît aidez-moi
VK Chikkadamalla
2

J'ai une solution similaire à @NealJMD, sauf que la mienne ne s'exécute que pour iOS et détermine correctement le décalage de défilement en mesurant le scollTop avant et après le défilement du clavier natif ainsi qu'en utilisant setTimeout pour permettre au défilement natif de se produire:

var $window = $(window);
var initialScroll = $window.scrollTop();
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
  setTimeout(function () {
    $window.scrollTop($window.scrollTop() + (initialScroll - $window.scrollTop()));
  }, 0);
}
ChrisWren
la source
1

J'ai fixé la position fixe du contenu de la mise en page principale de mon Ipad de cette façon:

var mainHeight;
var main = $('.main');

// hack to detects the virtual keyboard close action and fix the layout bug of fixed elements not being re-flowed
function mainHeightChanged() {
    $('body').scrollTop(0);
}

window.setInterval(function () {
    if (mainHeight !== main.height())mainHeightChanged();
    mainHeight = main.height();
}, 100);
Brett
la source
Cela a très bien fonctionné pour moi dans un mélange compliqué de dialogue d'interface utilisateur JQUery et de clavier à l'écran qui a laissé ma mise en page à mi-chemin de l'écran lorsque la boîte de dialogue et le clavier sont fermés en même temps, mais avec quelques modifications: var main = $ (' corps div '). first (); ... et ... function mainHeightChanged () {$ (top) .scrollTop (0); }
Awerealis
1
setInterval... vraiment? il vaut mieux rester avec le bogue que de faire ça
vsync
1

J'ai eu un problème similaire à @ ds111 s. Mon site Web a été poussé vers le haut par le clavier mais ne s'est pas déplacé vers le bas lorsque le clavier s'est fermé.

J'ai d'abord essayé la solution @ ds111 mais j'en avais deux input champs. Bien sûr, d'abord le clavier disparaît, puis le flou se produit (ou quelque chose comme ça). Alors le secondinput était donc sous le clavier, lorsque le focus passait directement d'une entrée à l'autre.

De plus, le "jump up" n'était pas assez bon pour moi car la page entière n'a que la taille de l'ipad. J'ai donc rendu le rouleau lisse.

Enfin, j'ai dû attacher l'écouteur d'événements à toutes les entrées, même celles qui étaient actuellement masquées, d'où le live.

Dans l'ensemble, je peux expliquer l'extrait de code javascript suivant comme suit: Attachez l'écouteur d'événement de flou suivant à l'actuel et à tous les futurs inputet textarea(= live): attendez une période de grâce (= window.setTimeout(..., 10)) et faites défiler en douceur vers le haut (= animate({scrollTop: 0}, ...)) mais seulement si "aucun clavier n'est montré "(= if($('input:focus, textarea:focus').length == 0)).

$('input, textarea').live('blur', function(event) {
    window.setTimeout(function() {
        if($('input:focus, textarea:focus').length == 0) {
            $("html, body").animate({ scrollTop: 0 }, 400);
        }
    }, 10)
})

Sachez que la période de grâce (= 10) peut être trop courte ou que le clavier peut toujours être affiché bien que non inputou textareasoit focalisé. Bien sûr, si vous souhaitez que le défilement soit plus rapide ou plus lent, vous pouvez ajuster la durée (= 400)

Raul Pinto
la source
1

vraiment travaillé dur pour trouver cette solution de contournement, qui en bref recherche les événements de mise au point et de flou sur les entrées, et le défilement pour modifier sélectivement le positionnement de la barre fixe lorsque les événements se produisent. Ceci est à toute épreuve et couvre tous les cas (navigation avec <>, défilement, bouton terminé). Remarque id = "nav" est mon div de pied de page fixe. Vous pouvez facilement le porter sur js ou jquery standard. C'est un dojo pour ceux qui utilisent des outils électriques ;-)

define (["dojo / ready", "dojo / query",], function (ready, query) {

ready(function(){

    /* This addresses the dreaded "fixed footer floating when focusing inputs and keybard is shown" on iphone 
     * 
     */
    if(navigator.userAgent.match(/iPhone/i)){
        var allInputs = query('input,textarea,select');
        var d = document, navEl = "nav";
        allInputs.on('focus', function(el){
             d.getElementById(navEl).style.position = "static";
        });

        var fixFooter = function(){
            if(d.activeElement.tagName == "BODY"){
                d.getElementById(navEl).style.position = "fixed";
            }
        };
        allInputs.on('blur', fixFooter);
        var b = d.body;
        b.addEventListener("touchend", fixFooter );
    }

});

}); // fin de définir

httpete
la source
Cela pourrait être génial ... le portage vers jQuery / js et vous en rendra compte. En passant, les solutions dans les choix de langage de script de niche qui nécessitent le portage ou l'ajout d'outils non standard à un projet ne seront pas, de manière prévisible, universellement utiles.
ericpeters0n
Cela ne fonctionnera pas dans tous les cas car cela vous fera défiler jusqu'à la position `` statique '' de l'élément, qui pourrait être à des kilomètres de la position d'origine de votre entrée, surtout si elle se trouve dans un conteneur fixe. Si le conteneur a une overflow:hiddenrègle, vous ne verrez pas du tout votre entrée car elle est maintenant en dehors de la boîte.
James M. Lay
1

C'est un problème difficile à résoudre. Vous pouvez essayer de masquer le pied de page sur le focus de l'élément d'entrée et l'afficher sur le flou, mais ce n'est pas toujours fiable sur iOS. De temps en temps (une fois sur dix, par exemple, sur mon iPhone 4S), l'événement de mise au point semble ne pas se déclencher (ou peut-être y a-t-il une condition de concurrence) et le pied de page n'est pas masqué.

Après de nombreux essais et erreurs, j'ai trouvé cette solution intéressante:

<head>
    ...various JS and CSS imports...
    <script type="text/javascript">
        document.write( '<style>#footer{visibility:hidden}@media(min-height:' + ($( window ).height() - 10) + 'px){#footer{visibility:visible}}</style>' );
    </script>
</head>

Essentiellement: utilisez JavaScript pour déterminer la hauteur de la fenêtre de l'appareil, puis créez dynamiquement une requête multimédia CSS pour masquer le pied de page lorsque la hauteur de la fenêtre se réduit de 10 pixels. Étant donné que l'ouverture du clavier redimensionne l'affichage du navigateur, cela n'échoue jamais sur iOS. Parce qu'il utilise le moteur CSS plutôt que JavaScript, c'est aussi beaucoup plus rapide et plus fluide!

Remarque: j'ai trouvé que l'utilisation de «visibilité: cachée» était moins glitch que «affichage: aucun» ou «position: statique», mais votre kilométrage peut varier.

Richard Kennard
la source
1
Vous devrez peut-être basculer entre la hauteur et la largeur pour résoudre ce problème pour les modes portrait et paysage.
Neil Monroe
1

Travaille pour moi

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'});
    });
}
ShibinRagh
la source
1

Dans notre cas, cela se corrigerait dès que l'utilisateur fait défiler. Voici donc le correctif que nous avons utilisé pour simuler un défilement blursur n'importe quel inputou textarea:

$(document).on('blur', 'input, textarea', function () {
    setTimeout(function () {
        window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
    }, 0);
});
basarat
la source
1

Ma réponse est que cela ne peut pas être fait.

Je vois 25 réponses mais aucune ne fonctionne dans mon cas. C'est pourquoi Yahoo et d'autres pages masquent l'en-tête fixe lorsque le clavier est activé. Et Bing rend la page entière non défilable (overflow-y: hidden).

Les cas évoqués ci-dessus sont différents, certains ont des problèmes lors du défilement, certains sur la mise au point ou le flou. Certains ont un pied de page ou un en-tête fixe. Je ne peux pas tester chaque combinaison maintenant, mais vous pourriez finir par réaliser que cela ne peut pas être fait dans votre cas.

Szalai Laci
la source
Cela ne répond pas à la question.
neophyte
4
C'est le cas, puisque la réponse est qu'il n'y a pas de solution.
Szalai Laci
0

J'ai trouvé cette solution sur Github.

https://github.com/Simbul/baker/issues/504#issuecomment-12821392

Assurez-vous que vous disposez d'un contenu déroulant.

// put in your .js file
$(window).load(function(){
    window.scrollTo(0, 1);
});

// min-height set for scrollable content
<div id="wrap" style="min-height: 480px">
  // website goes here
</div>

La barre d'adresse se replie comme un bonus supplémentaire.

Leigh Mackay
la source
0

Au cas où quelqu'un voudrait essayer ça. J'ai obtenu ce qui suit fonctionnant pour moi sur un pied de page fixe avec un champ d'entrée.

<script>
    $('document').ready(
        function() {
            if (navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)
                  || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/Windows Phone/i)) {
                var windowHeight = $(window).height();
                var documentHeight = $(document).height();

                $('#notes').live('focus', function() {
                    if (documentHeight > windowHeight) {
                        $('#controlsContainer').css({
                            position : 'absolute'
                        });
                        $("html, body").animate({
                            scrollTop : $(document).height()
                        }, 1);
                    }
                });
                $('#notes').live('blur', function() {
                    $('#controlsContainer').css({
                        position : 'fixed'
                    });
                    $("html, body").animate({
                        scrollTop : 0
                    }, 1);
                });
            }
        });
</script>
Bernard
la source
0

J'ai le même problème. Mais j'ai réalisé que la position fixe est juste retardée et non cassée (du moins pour moi). Attendez 5 à 10 secondes et voyez si le div s'ajuste vers le bas de l'écran. Je pense que ce n'est pas une erreur mais une réponse différée lorsque le clavier est ouvert.

Philippe
la source
0

J'ai essayé toutes les approches de ce fil, mais si elles n'aidaient pas, elles faisaient encore pire. En fin de compte, j'ai décidé de forcer l'appareil à perdre la mise au point:

$(<selector to your input field>).focus(function(){
    var $this = $(this);
    if (<user agent target check>) {
        function removeFocus () {
            $(<selector to some different interactive element>).focus();
            $(window).off('resize', removeFocus);
        }
        $(window).on('resize', removeFocus);
    }
});

et cela a fonctionné comme un charme et a corrigé mon formulaire de connexion collant.

Veuillez noter:

  1. Le code JS ci-dessus est uniquement pour présenter mon idée, pour exécuter cet extrait de code, veuillez remplacer les valeurs entre accolades angulaires (<>) par des valeurs appropriées à votre situation.
  2. Ce code est conçu pour fonctionner avec jQuery v1.10.2
Anton Boritskiy
la source
0

Il s'agit toujours d'un bogue important pour toutes les pages HTML avec des modaux Bootstrap plus grands dans iOS 8.3. Aucune des solutions proposées ci-dessus n'a fonctionné et après avoir zoomé sur n'importe quel champ sous le pli d'un grand modal, Mobile Safari et / ou WkWebView déplacerait les éléments fixes vers l'endroit où se trouvait le défilement du corps HTML, les laissant désalignés avec l'endroit où ils se trouvaient réellement. aménagé.

Pour contourner le bogue, ajoutez un écouteur d'événements à l'une de vos entrées modales comme:

$(select.modal).blur(function(){
  $('body').scrollTop(0);
});

Je suppose que cela fonctionne car le fait de forcer la hauteur de défilement du corps HTML réaligne la vue réelle avec l'endroit où iOS 8 WebView s'attend à ce que le contenu de la div modale fixe soit.

profondeurpremière conception
la source
0

Si quelqu'un cherchait un itinéraire complètement différent (par exemple, vous ne cherchez même pas à épingler ce div "pied de page" pendant que vous faites défiler mais vous voulez simplement que le div reste au bas de la page), vous pouvez simplement définir la position du pied de page comme relatif.

Cela signifie que même si le clavier virtuel apparaît sur votre navigateur mobile, votre pied de page restera simplement ancré au bas de la page, sans essayer de réagir à l'affichage ou à la fermeture du clavier virtuel.

Évidemment, cela a l'air mieux sur Safari si la position est fixe et que le pied de page suit la page lorsque vous faites défiler vers le haut ou vers le bas, mais à cause de ce bogue étrange sur Chrome, nous avons fini par passer à simplement rendre le pied de page relatif.

Terry Bu
la source
0

Aucune des solutions de défilement ne semblait fonctionner pour moi. Au lieu de cela, ce qui a fonctionné est de définir la position du corps sur fixe pendant que l'utilisateur modifie le texte, puis de le restaurer en statique lorsque l'utilisateur a terminé. Cela empêche Safari de faire défiler votre contenu sur vous. Vous pouvez le faire soit sur la mise au point / le flou du ou des éléments (indiqués ci-dessous pour un seul élément mais pourrait être pour toutes les entrées, zones de texte), ou si un utilisateur fait quelque chose pour commencer l'édition comme ouvrir un modal, vous pouvez faire sur cette action (par exemple ouverture / fermeture modale).

$("#myInput").on("focus", function () {
    $("body").css("position", "fixed");
});

$("#myInput").on("blur", function () {
    $("body").css("position", "static");
});
Scott Semyan
la source
0

iOS9 - même problème.

TLDR - source du problème. Pour la solution, faites défiler vers le bas

J'avais un formulaire dans une position:fixediframe avec id = 'subscribe-popup-frame'

Conformément à la question d'origine, lors de la mise au point d'entrée, l'iframe irait en haut du document par opposition au haut de l'écran.

Le même problème ne s'est pas produit en mode de développement safari avec l'agent utilisateur défini sur un périphérique. Il semble donc que le problème soit causé par le clavier virtuel iOS lorsqu'il apparaît.

J'ai eu une certaine visibilité sur ce qui se passait en enregistrant la position de l'iframe par la console (par exemple $('#subscribe-popup-frame', window.parent.document).position()) et à partir de là, je pouvais voir qu'iOS semblait définir la position de l'élément à{top: -x, left: 0} moment où le clavier virtuel apparaissait (c'est-à-dire concentré sur l'élément d'entrée).

Ma solution était donc de prendre cette embêtante -x, d'inverser le signe, puis d'utiliser jQuery pour ajouter cette topposition à l'iframe. S'il y a une meilleure solution, j'aimerais l'entendre, mais après avoir essayé une douzaine d'approches différentes, c'est la seule qui a fonctionné pour moi.

Inconvénient: j'avais besoin de définir un délai d'expiration de 500 ms (peut-être moins fonctionnerait mais je voulais être sûr) pour m'assurer de capturer la xvaleur finale après qu'iOS ait fait son mal avec la position de l'élément. En conséquence, l'expérience est très saccadée. . . mais au moins ça marche

Solution

        var mobileInputReposition = function(){
             //if statement is optional, I wanted to restrict this script to mobile devices where the problem arose
            if(screen.width < 769){
                setTimeout(function(){
                    var parentFrame = $('#subscribe-popup-frame',window.parent.document);
                    var parentFramePosFull = parentFrame.position();
                    var parentFramePosFlip = parentFramePosFull['top'] * -1;
                    parentFrame.css({'position' : 'fixed', 'top' : parentFramePosFlip + 'px'});
                },500);
            }    
        }   

Ensuite, appelez simplement mobileInputRepositionquelque chose comme $('your-input-field).focus(function(){})et$('your-input-field).blur(function(){})

Martellalex
la source