web-dev-qa-db-fra.com

iOS Safari/Chrome - Défilement indésirable lors de la mise au point d'une entrée à l'intérieur du modal

Testé dans Safari et Chrome - le même résultat, donc je pense que c'est un problème iOS.

Cela se produit uniquement s'il y a une entrée à l'intérieur du modal et que je tape sur cette entrée. Au même moment, cette entrée devient active et le clavier iOS natif devient visible. 

La page ci-dessous modale au même moment défile automatiquement à 50% de sa hauteur. Ce comportement est totalement indésirable et je ne sais pas comment empêcher cette "fonctionnalité" par défaut d'iOS.

Démo:

 enter image description here

18
Limon Monte

Ajoutez simplement une réponse ici au cas où des personnes tomberaient sur cette question ( plutôt que votre autre question, qui présente une excellente démo pour illustrer ce problème )

Nous sommes confrontés à un problème similaire au travail. Comme vous l'avez mentionné, le décalage correspond toujours à environ 50% de la hauteur de la page, ce qui se produit quel que soit le niveau de votre décalage initial.

Dans le passé, lorsque j’observais un "saut" similaire avec des versions antérieures d’iOS (bien que beaucoup moins dramatique), j’avais l'habitude de contourner ce problème en appliquant position: fixed (ou relative) à la body ( qui permet à overflow: hidden de fonctionner correctement ). 

Cependant, cela a pour conséquence involontaire de ramener l'utilisateur au haut de la page, s'il a fait défiler l'écran.

Donc, si vous êtes prêt à résoudre ce problème avec un JavaScript, voici un correctif/hack que j'ai jeté ensemble:

// Tapping into swal events
onOpen: function () {
  var offset = document.body.scrollTop;
  document.body.style.top = (offset * -1) + 'px';
  document.body.classList.add('modal--opened');
},
onClose: function () {
  var offset = parseInt(document.body.style.top, 10);
  document.body.classList.remove('modal--opened');
  document.body.scrollTop = (offset * -1);
}

Et à quoi ressemble le CSS:

.modal--opened {
  position: fixed;
  left: 0;
  right: 0;
}

Voici une fourchette de votre page de démonstration (de votre autre question), pour illustrer: https://jpattishall.github.io/sweetalert2/ios-bug.html

Et pour ceux qui recherchent une solution plus générale, vous pouvez procéder comme suit pour ouvrir/fermer un modal:

function toggleModal() {
    var offset;
    if (document.body.classList.contains('modal--opened')) {
        offset = parseInt(document.body.style.top, 10);
        document.body.classList.remove('modal--opened');
        document.body.scrollTop = (offset * -1);
    } else {
        offset = document.body.scrollTop;
        document.body.style.top = (offset * -1) + 'px';
        document.body.classList.add('modal--opened');
    }
}

Edit: Pour éviter le "décalage/décalage" sur les ordinateurs de bureau, je suggérerais la détection de fonctionnalité/le reniflement ua pour l’appliquer uniquement au safari mobile.

10
Jack

Donc, j'ai résolu ce problème et testé sur mon iPhone 5, je n'ai pas d'Ipad à vérifier . J'ai désactiver overflow:hidden dans ma solution, vous pouvez ajouter, si vous souhaitez désactiver le défilement tout en un pour tous les modaux ..__ La solution consiste à ajouter essentiellement les propriétés height et position aux éléments html et body. 

html, body {
   position:relative;
   /*overflow:hidden;*/
   height: 100%;
}

Donc, ce n'est que lorsque vous vous concentrez sur l'entrée, la hauteur et la position seront définies, j'ai déjà codé cette solution depuis votre dépôt, je vous enverrai une demande d'extraction. J'ai également ajouté browserSync dans votre configuration gulp. Par conséquent, il sera maintenant facile de tester tous les appareils.

À votre santé!

EDIT: une autre façon, si la solution ci-dessus ne fonctionne pas pour une raison quelconque. puis,

 /*
  * @summary touch handler; will remove touch ability
  * @author yeomann
  */
  function Touchyhandler(e) {
    e.preventDefault();
  }

et plus tard ajouter et supprimer de manière pragmatique des écouteurs tactiles comme celui-ci

//to add
document.addEventListener('touchmove', Touchyhandler, false); 
//to remove   
document.removeEventListener('touchmove', Touchyhandler);

ci-dessus la solution js testée sur IOS 9.3.2 fonctionne à merveille pour moi]

1
Danish

J'ai essayé plusieurs choses qui ont fonctionné pour les entrées modales renvoyées sur la page HTML. La solution la plus simple qui a fonctionné pour moi a été d'ajouter les styles suivants à la balise body lorsque le modal est ouvert sur la page.

position: fixed;
width: 100%;
0
Manohar Mankala

J'ai connu ce problème aussi. Une explication brève est qu'iOS Safari essaiera de faire défiler automatiquement l'entrée sélectionnée et que, dans ce cas particulier, l'élément ciblé se trouve dans un élément positionné fixe. Safari semble avoir du mal à trouver l'élément à position fixe lorsqu'il veut centrer l'élément sur l'écran, d'où le défilement en arrière-plan. 

Une solution possible est d’ajouter un écouteur d’événement touchstart au champ de saisie et de calculer la position actuelle de la superposition, de modifier le positionnement en absolu et de mettre à jour la position haut/gauche pour replacer la superposition là où elle était à l’écran, et enfin, ajoutez un nouvel écouteur blur pour réinitialiser la superposition au positionnement fixe tout en laissant le focus/flou sur l'entrée. Cela devrait empêcher la page de défiler. Je suggère d'utiliser touchstart car cela devrait se déclencher avant l'événement focus, auquel cas la page commence déjà à défiler. Safari devrait pouvoir trouver et centrer la superposition positionnée absolue lorsque l'événement focus est déclenché.

0
DKrautkramer

Je ne suis pas sûr à 100% mais je peux imaginer ce qui suit:

Lorsque le clavier apparaît, la hauteur de la fenêtre diminue, mais la valeur scrollTop est toujours la même et le site passe alors à cette valeur. Vous pouvez ajouter overflow:hidden à la body lorsque le modal est ouvert. Cela bloquera le défilement "derrière" le modal et résoudra probablement votre problème.

0
Kilian So