web-dev-qa-db-fra.com

-webkit-overflow-scrolling: appuyez sur casse dans iOS8 d'Apple

Je travaille sur une application Web qui utilise -webkit-overflow-scrolling:touch à plusieurs endroits pour donner le défilement à l'inertie des divs survolés.

Depuis la mise à jour vers IOS8, -webkit-overflow-scrolling: touch vous empêche de faire défiler quoi que ce soit, et la seule façon pour moi de résoudre ce problème consiste à supprimer -webkit-overflow-scrolling: touch qui laisse le défilement standard persistant. S'il vous plaît aider!

Voici un exemple de l'une des classes standard qui fonctionne dans iOS5, 6 et 7:

.dashboardScroll {
    height: 100%;
    overflow-x: hidden;
    overflow-y: scroll;
    -webkit-overflow-scrolling: touch; /*MAKES OVERFLOWN OBJECTS HAVE INERTIA SCROLLING*/
    -webkit-transform: translateZ(0px); /*HELPS THE ABOVE WORK IN IOS5*/
} 
54
Jamie Beech

J'ai eu un problème similaire avec un div (assez complexe) à défilement imbriqué qui défilait très bien dans iOS 5, 6 et 7, mais qui échouait de façon intermittente dans iOS 8.1.

La solution que j'ai trouvée consistait à supprimer tout le CSS qui incite le navigateur à utiliser le GPU:

-webkit-transform: translateZ(0px);
-webkit-transform: translate3d(0,0,0);
-webkit-perspective: 1000;

En faisant cela, le '-webkit-overflow-scrolling: touch;' peut toujours être inclus et continuer à fonctionner normalement.

Cela signifiait sacrifier les gains (pour moi, douteux) sur les performances de défilement que les hacks ci-dessus avaient données lors d'incarnations antérieures d'iOS, mais dans le choix entre cela et le défilement par inertie, le défilement par inertie était jugé plus important (et nous ne soutenons pas iOS 5 plus).

Je ne peux pas, à ce stade, dire pourquoi ce conflit existe; c'est peut-être une mauvaise implémentation de ces fonctionnalités, mais je suppose qu'il y a quelque chose d'un peu plus profond dans le CSS qui le cause. J'essaie actuellement de créer une configuration HTML/CSS/JS réduite pour le démontrer, mais peut-être que la structure de balisage lourde et les grandes quantités de données dynamiques sont nécessaires pour que cela se produise.

Addendum: Je devais cependant signaler à notre client que si même avec ce correctif, l'utilisateur essayait de faire défiler un élément non défilable, il devait attendre une seconde après son arrêt avant de pouvoir faire défiler l'élément défilable. C'est un comportement indigène.

27
Louis Féat

J'ai eu ce problème et trouvé une solution. La solution est que vous devez placer votre contenu dans deux conteneurs, par exemple :(. DashboardScroll> .dashboardScroll-inner) et donner au conteneur interne ".dashboardScroll-inner" 1px plus de hauteur que le parent ".dashboardScroll" via ce css3 propriété 

.dashboardScroll-inner { height: calc(100% + 1px);}

regarde ça :

http://patrickmuff.ch/blog/2014/10/01/how-we-fixed-the-webkit-overflow-scrolling-touch-bug-on-ios/

ou bien si vous ne pouvez pas ajouter un autre conteneur, utilisez ceci:

.dashboardScroll:after { height: calc(100% + 1px);}
9
mohammed Suleiman

J'ai eu le même problème dans une application web Cordova. Pour moi, le problème était que j'avais un <div> parent qui était animé et qui avait la propriété animation-fill-mode: forwards; 

La suppression de cette propriété a résolu le problème et corrigé le défilement par débordement interrompu.

6
clauderic

J'ai essayé toutes les solutions ici sans succès. Je pouvais le faire fonctionner en ayant la propriété -webkit-overflow-scrolling: touch; sur le div scrollable AND sur le conteneur parent.

div.container {
    -webkit-overflow-scrolling: touch;
}

div.container > div.scrollable {
    -webkit-overflow-scrolling: touch;
    overflow-y: auto;
}
2
Gabriel Bull

Empêcher les événements tactiles de faire remonter les éléments environnants dans le DOM est une autre solution potentielle. Vous remarquerez peut-être que le défilement s'arrête lorsque les éléments DIV environnants reçoivent les événements tactiles ou de déplacement. Nous avions ce problème particulier dans un menu qui devait défiler en douceur. La désactivation de ces événements a contribué à empêcher le "blocage" de l'élément capable de défilement. 

$html.bind('touchmove', scrollLock );

var scrollLock = function(e) {
        if( $body.hasClass('menu-open') ){
                e.stopPropagation();
                e.preventDefault();
        }
};

$html.unbind('touchmove', scrollLock );
1
Squiggs.

Je n'ai pas pu résoudre le problème avec les réponses précédentes. Ainsi, après quelques heures, la bibliothèque iScroll a été testée, iScroll . Je sais qu’ajouter une bibliothèque supplémentaire (et assez importante) pour ajouter du défilement à iOS, ce n’est pas génial, mais c’est ce qui a fonctionné pour moi. Il suffit de suivre le readme, la version allégée suffit.

Désavantages:

  • Faire défiler sur Android ressemble maintenant à de la merde, ce n'est plus natif.
  • Il n'est plus possible d'actualiser la page en faisant défiler
  • Vous devez appliquer un autre correctif pour Android: Les clics ne fonctionnent pas

Je ne sais pas si je vais l'utiliser, mais si vous en avez besoin, essayez-le.

1
CapK

J'ai eu quelques problèmes avec cela aussi, mais dans un scénario légèrement différent.

J'ai mes divs avec inertie sans aucun problème.

J'ai un simple JSFiddle où vous pouvez jeter un coup d'oeil.

https://jsfiddle.net/SergioM/57f2da87/17/

.scrollable {
    width:100%;
    height:200px;
    -webkit-overflow-scrolling:touch;
    overflow:scroll;
}

J'espère que ça aide.

0
SergioM

J'ai utilisé la dernière méthode dans la réponse de mohammed Suleiman (.dashboardScroll: after {height: calc (100% + 1px);}), mais le résultat était que j'avais un espace vide de 100% + 1px en dessous de mon contenu. J'ai corrigé cela en modifiant la hauteur à 1px après 500ms. Moche, mais ça marche.

C'était une application react.js donc mon code était comme ça:

componentDidUpdate() {
    if (window.navigator.standalone && /* test for iOS */) {
        var self = this;
        setTimeout(function(){
            self.refs.style.innerHTML = "#content::after { height: 1px}";
        }, 500);
    }
}

et rendre:

render() {
    var style = '';
    if (window.navigator.standalone && /* test for iOS */) {
        style = "#content::after { height: calc(100% + 1px)}";
    }
    return (<div>
                <style type="text/css" ref="style">
                    {style}
                </style>
                <div id="content"></div>
            </div>);
}
0
Dagligleder

J'ai eu ce problème en utilisant le modal bootstrap angulaire. Je l'ai corrigé en créant ma propre feuille de style et en supprimant la largeur et la marge fixes dans les requêtes de support. 

ORIGINAL:

  .modal-dialog {
    position: relative;
    width: auto;
    margin: 10px;
  }

@media (min-width: 768px) {
  .modal-dialog {
      width: 600px;
      margin: 30px auto;
  }
    .modal-content {
        -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
        box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
    }
    .modal-sm {
        width: 300px;
    }
}
@media (min-width: 992px) {
    .modal-lg {
        width: 900px;
    }
}

CHANGEMENTS:

.modal-dialog {
    margin: 0px;
    margin-top: 30px;
    margin-left: 5%;
    margin-right: 5%;
}

@media (min-width: 768px) {
    .modal-dialog {
        width: auto;
        margin-left: 10%;
        margin-right: 10%;
    }
    .modal-content {
       -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
       box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
    }
}

@media (min-width: 992px) {
    .modal-dialog {
        width: auto;
        margin-left: 15%;
        margin-right: 15%;
    }  
}
0
Nikki Lehman