web-dev-qa-db-fra.com

Le défilement iPad Safari entraîne la disparition et la réapparition d'éléments HTML

Je développe actuellement une application Web utilisant html5 et jQuery pour iPad Safari. Je rencontre un problème en raison duquel de grandes zones de défilement provoquent l’apparition des éléments hors écran après un certain délai lorsque je les fais défiler.

Ce que je veux dire par là, c'est que si j'ai une rangée d'images (ou même une div avec un dégradé) qui est hors écran, quand je fais défiler vers le bas (ou vers le haut), le comportement attend est pour l'élément à afficher à l'écran lorsque je le fais défiler.

Cependant, ce que je constate, c’est que l’élément n’apparaît pas jusqu’à ce que je lève le doigt de l’écran et que le défilement termine toutes ses animations.

Cela cause un problème remarquable pour moi, ce qui donne une impression de déséquilibre, bien que ce ne soit pas le cas. J'imagine que l'iPad Safari tente de faire quelque chose pour économiser de la mémoire. Y at-il un moyen par lequel je peux empêcher cette agitation de se produire. De plus, j'apprécierais également que quiconque puisse faire la lumière sur ce que l'iPad Safari tente réellement de faire.

157
codeBearer

Ceci est la réponse complète à ma question. J'avais initialement marqué la réponse de @Colin Williams comme étant la bonne réponse, car elle m'a aidé à trouver la solution complète. Un membre de la communauté, @Slipp D. Thompson a modifié ma question, après environ deux ans et demi de demande, et d’abus du format de questions-réponses de SO, il m’a également demandé d’afficher cela séparément comme réponse. Voici donc la réponse complète qui a résolu mon problème:

@Colin Williams, merci! Votre réponse et l'article que vous avez publié vous ont permis d'essayer quelque chose avec CSS.

Donc, j'utilisais translate3d avant. Cela a produit des résultats indésirables. En gros, cela coupait et ne rendait pas les éléments hors écran, jusqu'à ce que j'interagisse avec eux. Donc, en gros, en orientation paysage, la moitié de mon site qui était hors écran n'était pas affichée. Ceci est une application web iPad, en raison de laquelle j'étais dans une situation difficile.

L’application de translate3d à des éléments relativement positionnés a résolu le problème, mais d’autres éléments ont arrêté le rendu, une fois hors écran. Les éléments avec lesquels je ne pouvais pas interagir (illustration) ne seraient plus jamais rendus, à moins que je ne recharge la page.

La solution complète:

*:not(html) {
    -webkit-transform: translate3d(0, 0, 0);
}

Bien que cette solution ne soit peut-être pas la plus "efficace", c’est la seule qui fonctionne. Mobile Safari ne rend pas les éléments hors écran, ni parfois de manière erratique, lorsque vous utilisez -webkit-overflow-scrolling: touch. À moins qu'un translate3d ne soit appliqué à tous les autres éléments susceptibles de passer hors écran en raison de ce défilement, ces éléments seront coupés après le défilement.

Alors, merci encore et espérons que cela aide une autre âme perdue. Cela m'a sûrement aidé beaucoup!

64
codeBearer

Vous devez piéger le navigateur pour utiliser l'accélération matérielle plus efficacement. Vous pouvez le faire avec une transformation 3d vide:

-webkit-transform: translate3d(0,0,0)

En particulier, vous en aurez besoin pour les éléments enfants qui ont une déclaration position:relative; (ou, tout simplement, et faites-le pour tous les éléments enfants).

Pas une solution garantie, mais plutôt réussie la plupart du temps.

Astuce de chapeau: https://web.archive.org/web/20131005175118/http://cantina.co/2012/03/06/ios-5-native-scrolling-grins-and-gothcas/

177
Colin Williams

Le ciblage de tous les éléments sauf html: *:not(html) a provoqué des problèmes sur d'autres éléments dans mon cas. Cela modifiait le contexte d'empilement, causant la rupture de certains z-index.

Nous devrions mieux essayer de cibler le bon élément et ne lui appliquons que -webkit-transform: translate3d(0,0,0).

Edit: Parfois, la translate3D(0,0,0) ne fonctionne pas, nous pouvons utiliser la méthode suivante, en ciblant le bon élément:

@keyframes redraw{
    0% {opacity: 1;}
    100% {opacity: .99;}
}

// ios redraw fix
animation: redraw 1s linear infinite;
12

Lorsque le translate3d ne fonctionne pas, essayez d'ajouter une perspective. Ça marche toujours pour moi

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

http://blog.teamtreehouse.com/increase-your-sites-performance-with-hardware-accelerated-css

6
Fellipe Lima

Ajouter -webkit-transform: translate3d(0,0,0) à un élément de manière statique ne fonctionne pas pour moi.

J'applique cette propriété de manière dynamique. Par exemple, quand une page défile, je règle -webkit-transform: translate3d(0,0,0) sur un élément. Puis, après un court délai, je réinitialise cette propriété, c'est-à-dire -webkit-transform: none Cette approche semble fonctionner.

Merci @Colin Williams de m'avoir orienté dans la bonne direction.

2

J'ai eu le même problème avec iscroll 4.2.5 sur iOS 7. L'élément de défilement entier disparaît tout simplement. J'ai essayé d'ajouter translate3d(0,0,0) comme suggéré ici, le problème a été résolu, mais il a désactivé l'effet "snap" iscroll. La solution est venue en donnant les propriétés "position:relative; z-index:1000;display:block" css à l'ensemble du conteneur qui contient l'élément scroll et il n'est pas nécessaire de donner translate3d aux éléments enfants.

1
yudarik

Il s'agit d'un problème très courant rencontré par les développeurs et qui est principalement dû à la propriété Safari's de ne pas recréer les éléments définis comme position : fixed.

Donc, soit modifier la propriété de la position, soit un hack doit être appliqué comme indiqué dans d'autres réponses.

Link1

Link2

0
arqam

J'ai fait face à ce problème dans un projet Framework7 & Cordova. J'ai essayé toutes les solutions ci-dessus. Ils n'ont pas résolu mon problème.

Dans mon cas, j'utilisais plus de 10 animations CSS sur la même page avec une rotation infinie (transformation). J'ai dû supprimer les animations. C'est ok maintenant avec le manque de certaines fonctionnalités visuelles.

Si les solutions ci-dessus ne vous aident pas, vous pouvez commencer à éliminer certaines animations.

0
yavuzkirez

Dans mon cas (une application iOS Phonegap), appliquer translate3d à des éléments enfants relatifs ne résolvait pas le problème. Mon élément déroulant n'avait pas de hauteur définie car il était parfaitement positionné et je définissais les positions du haut et du bas. Ce qui l’a corrigé pour moi a été l’ajout d’une hauteur minimale (100px).

0
b4tch

J'ai eu le même problème en utilisant une ancienne version de Fancybox. La mise à niveau vers la v3 résoudra votre problème OR vous pouvez simplement ajouter:

html, body {
    -webkit-overflow-scrolling : touch !important;
    overflow: auto !important;
    height: 100% !important;
}
0
Adam Touhou

Il existe des cas où un rotation est appliqué et/ou un Z index est utilisé.

Rotation: Une déclaration existante de -webkit-transform pour faire pivoter un élément peut ne pas suffire pour résoudre également le problème de l'apparence (comme -webkit-transform: rotate(-45deg)). Dans ce cas, vous pouvez utiliser -webkit-transform: translateZ(0px) rotateZ(-45deg) comme une astuce (, faites attention à la rotation Z).

index Z: Avec la rotation, vous pouvez définir une propriété positive z-index, telle que z-index: 42. Les étapes ci-dessus décrites dans "Rotation" suffisaient dans mon cas à résoudre le problème, même avec le translateZ(0px) vide. Je suppose cependant que l’indice Z dans ce cas peut avoir causé la disparition et la réapparition en premier lieu. Dans tous les cas, la propriété z-index: 42 doit être conservée - -webkit-transform: translateZ(42px) seulement ne suffit pas.

0
Stefan Zurfluh

Je suis vraiment sûr d'avoir résolu ce problème avec:

overflow-y: auto;

(Vraisemblablement, juste overflow: auto; fonctionnerait aussi en fonction de vos besoins.)

0
David Notik

Au moment translate3d peut ne pas fonctionner, dans ce cas perspective peut être utilisé

transform: translate3d(0, 0, 0);
-webkit-transform: translate3d(0, 0, 0);
perspective: 1000;
-webkit-perspective: 1000;
0
Nidhin Joseph