Beim Scrollen mit iPad Safari verschwinden HTML-Elemente und werden verzögert wieder angezeigt

165

Ich entwickle derzeit eine Web-App mit HTML5 und jQuery für iPad Safari. Ich habe ein Problem, bei dem große Bildlaufbereiche dazu führen, dass die Elemente außerhalb des Bildschirms nach einer Verzögerung angezeigt werden, wenn ich zu ihnen scrolle.

Was ich damit meine ist, wenn ich eine Reihe von Bildern (oder sogar ein Div mit einem Farbverlauf) außerhalb des Bildschirms habe , wenn ich nach unten (oder oben) scrolle, ist das erwartete Verhalten, dass das Element auf dem Bildschirm als angezeigt wird Ich scrolle dorthin.

Aber was ich sehe ist , dass das Element nicht angezeigt , bis ich meine Finger vom Bildschirm und das Stellrad beendet heben alle seine Animationen.

Dies verursacht für mich ein sehr auffälliges Problem, das das Ganze abgehackt aussehen lässt, obwohl dies nicht der Fall ist. Ich vermute, das iPad Safari versucht etwas zu tun, um Speicherplatz zu sparen. Gibt es eine Möglichkeit, wie ich verhindern kann, dass diese Unruhe entsteht? Darüber hinaus würde ich mich auch freuen, wenn jemand Aufschluss darüber geben kann, was die iPad Safari tatsächlich versucht.

codeBearer
quelle
Dieses Problem / diese Lösung hat mir geholfen, ein Problem mit der CSS Transforms-Version von jPanelMenu 1.3 zu beheben, bei dem alles auf meiner Website unsichtbar wurde, bis ich das obige Snippet hinzufügte.
75. Posaune
2
Wenn Sie *: not (html) verwenden, wird translate3d auf alle anderen Aspekte Ihrer Website angewendet, und ich empfehle dies nicht. Es führt dazu, dass Bilder in Registerkarten verschwinden, wenn Sie nach unten scrollen usw. Fehler, die Sie möglicherweise nur auf Ihren 3D-Bildern sehen, sind jetzt in anderen Aspekten Ihrer Website vorhanden.
Jonathan Tonge
1
Ich hatte einige <svg>Elemente, die ein ähnliches verzögertes Zeichnen / Rendern zeigten. Leider *:not(html) { ... }führte dies zu allerlei seltsamen Verhaltensweisen, wie @JonathanTonge hervorhob. Die Auswahl nur der <svg>Elemente und die Verwendung translate3d(0, 0, 0,);scheinen jedoch meine Bildlaufprobleme gelöst zu haben.
Zephyr Mays
Mit Ausnahme sehr spezifischer Anwendungsfälle ist dies Müll. Versaut wirklich Layouts, die von absoluten Positionselementen abhängen.
Stoutie
2
Bitte posten Sie Antworten als Antworten, nicht als "BEARBEITEN" in Ihrer Frage. Ich weiß, dass Ihnen Ihre Antwort am besten gefällt, und das ist in Ordnung, aber StackOverflow hat ein Q & A-Format, das am besten funktioniert, wenn sich die Qs von den A's unterscheiden.
Slipp D. Thompson

Antworten:

184

Sie müssen den Browser austricksen, um die Hardwarebeschleunigung effektiver nutzen zu können. Sie können dies mit einer leeren 3D-Transformation tun:

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

Insbesondere benötigen Sie dies für untergeordnete Elemente, die eine position:relative;Deklaration haben (oder gehen Sie einfach alles aus und tun Sie es für alle untergeordneten Elemente).

Keine garantierte Lösung, aber die meiste Zeit ziemlich erfolgreich.

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

Colin Williams
quelle
3
Das habe ich auch versucht. Leider werden beim Hinzufügen einer translate3d Elemente abgeschnitten, die zuvor ordnungsgemäß angezeigt wurden. Ich brauchte auch Hardwarebeschleunigung für ein paar Objekte, die sich außerhalb des Bildschirms befanden und animiert werden mussten, um auf dem Bildschirm "hineinzufliegen". Ich habe jQuerys animate () verwendet, was sehr langsam war. Ich habe auf Hardwarebeschleunigung umgestellt. Obwohl dies die Animation beschleunigte, führte dies zu fehlerhaften Ergebnissen in dem Sinne, dass einige der untergeordneten Elemente des übergeordneten (animierenden) Div abgeschnitten wurden. Dies geschah nicht, als ich animate () verwendete.
CodeBearer
1
@Colin Williams du hast gerade meinen Tag gemacht! : D
Luke
9
Wow, das ist schrecklich, aber effektiv. Danke dir.
Tim Down
1
Gold verdammter Star Mann! Ich habe es allen meinen Li-Elementen in einem scrollbaren Div hinzugefügt. Poof. Hat funktioniert.
Bryan Johnson
68

Dies ist die vollständige Antwort auf meine Frage. Ich hatte ursprünglich die Antwort von @Colin Williams als die richtige Antwort markiert, da dies mir half, zur vollständigen Lösung zu gelangen. Ein Community-Mitglied, @Slipp D. Thompson, hat meine Frage bearbeitet, nachdem ich sie etwa 2,5 Jahre lang gestellt hatte, und mir mitgeteilt, dass ich das Q & A-Format von SO missbraucht habe. Er sagte mir auch, ich solle dies separat als Antwort posten. Hier ist die vollständige Antwort, die mein Problem gelöst hat:

@Colin Williams, danke! Ihre Antwort und der Artikel, auf den Sie verlinkt haben, haben mich dazu veranlasst, etwas mit CSS auszuprobieren.

Also habe ich zuvor translate3d verwendet. Es wurden unerwünschte Ergebnisse erzielt. Grundsätzlich würde es Elemente, die sich außerhalb des Bildschirms befanden, abhacken und NICHT RENDEREN, bis ich mit ihnen interagierte. Im Querformat wurde also die Hälfte meiner Website, die sich außerhalb des Bildschirms befand, nicht angezeigt. Dies ist eine iPad-Web-App, aufgrund derer ich in einem Fix war.

Das Anwenden von translate3d auf relativ positionierte Elemente löste das Problem für diese Elemente, aber andere Elemente wurden nach dem Bildschirm nicht mehr gerendert. Die Elemente, mit denen ich nicht interagieren konnte (Grafik), würden nie wieder gerendert, wenn ich die Seite nicht neu geladen hätte.

Die Komplettlösung:

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

Obwohl dies möglicherweise nicht die "effizienteste" Lösung ist, war es die einzige, die funktioniert. Mobile Safari rendert die Elemente nicht außerhalb des Bildschirms oder manchmal unregelmäßig, wenn sie verwendet werden-webkit-overflow-scrolling: touch . Sofern nicht ein translate3d auf alle anderen Elemente angewendet wird, die aufgrund dieses Bildlaufs möglicherweise vom Bildschirm verschwinden, werden diese Elemente nach dem Bildlauf abgeschnitten.

Also nochmals vielen Dank und hoffe, dass dies einer anderen verlorenen Seele hilft. Das hat mir sicherlich sehr geholfen!

codeBearer
quelle
2
Beeindruckend. Danke dafür. Es ersparte mir eine Menge Kopfschmerzen für meine Phonegap / Cordova-App. In meinem Fall musste ich *:not(html)umbody *
anon
9
Nur -webkit-transform: translate3d(0, 0, 0);auf das Problemelement anzuwenden , hat bei mir funktioniert. In meinem Fall habe ich ScrollMagic
fidev
Nichts davon hat auch für mich funktioniert. Sobald ich bis zu einem bestimmten Punkt nach unten scrolle, werden das nicht mehr sichtbare Material über dem Fenster sowie einige Elemente im Ansichtsfenster entfernt. Ich bemerke einen sehr leichten, aber unverkennbaren "Ruck" beim Scrollen, wonach die Elemente abgespritzt werden. (Dh: glattes - nervöses - glattes Verhalten, als würde es beim Scrollen Schluckauf geben.) Dies ist auf dem iPad der Fall.
cbmtrx
Übrigens habe ich gerade festgestellt, dass auf einem iPad Air 2, wenn ein bestimmtes Bildschirmelement (in diesem Fall eine Navigationsleiste) vom Bildschirm verschwindet, das Gerät diesen Block "neu lädt" - nur mit der großen Version, nicht mit der ursprünglichen mittleren Version dass die Seite mit geladen. Was zum ...
cbmtrx
Für den Fall, dass jemand die gleiche Verrücktheit wie ich hat - etwas anders als auf dieser Seite beschrieben -, habe ich festgestellt, dass die Verwendung $(window).width()anstelle von window.innerWidthin jQuery den Unterschied für iOS ausmacht. Wer weiß.
cbmtrx
13

Targeting aller Elemente außer HTML: *:not(html) verursachte in meinem Fall Probleme mit anderen Elementen. Es hat den Stapelkontext geändert und dazu geführt, dass ein Z-Index unterbrochen wurde.

Wir sollten besser versuchen, das richtige Element zu finden und anzuwenden-webkit-transform: translate3d(0,0,0) .

Bearbeiten: Manchmal translate3D(0,0,0)funktioniert das nicht. Wir können die folgende Methode verwenden, die auf das richtige Element abzielt:

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

// ios redraw fix
animation: redraw 1s linear infinite;
Guillaume Gautier
quelle
Ich stand vor dem gleichen Problem. Sie können den body *Selektor anstelle von verwenden *:not(html). Es wird Ihr Problem lösen.
Kunal
Ein großes Lob für den Vorschlag, die richtigen Elemente anzuvisieren, anstatt alles mit dem *
Maciek Rek
7

Wenn die translate3d nicht funktioniert, versuchen Sie, eine Perspektive hinzuzufügen. Es funktioniert immer bei mir

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

Fellipe Lima
quelle
heiliges c $ # @ endlich eine lösung für eckig / ionisch. -webkit-perspective: 1000;
Lilbiscuit
Ahh hat meinen Tag gerettet. +1 für Sie;)
Omar Bahir
Dadurch stürzte mein iOS-Browser ab.
Andreas Richter
-webkit-perspective: 1000;tat es für mich - danke
jHilscher
2

Hinzufügen -webkit-transform: translate3d(0,0,0) statische zu einem Element funktioniert bei mir nicht.

Ich wende diese Eigenschaft dynamisch an. Wenn zum Beispiel eine Seite gescrollt wird, setze ich -webkit-transform: translate3d(0,0,0)ein Element. Nach einer kurzen Verzögerung setze ich diese Eigenschaft zurück, d. H.-webkit-transform: none Ansatz scheint zu funktionieren.

Vielen Dank, @Colin Williams, dass Sie mich in die richtige Richtung weisen.

Alexander Poleschuk
quelle
Dieser Hinweis hat mir sehr geholfen, da diese Stile einige unerwünschte Nebenwirkungen haben, die ich normalerweise vermeiden möchte. Also benutze ich Touchstart / Touchend-Ereignisse, um sie hinzuzufügen und zu entfernen. Vielen Dank!
Windwalker
1

Ich hatte das gleiche Problem mit iscroll 4.2.5 auf ios7. Das gesamte Bildlaufelement verschwindet einfach. Ich habe versucht hinzuzufügen, translate3d(0,0,0)wie hier vorgeschlagen, es hat das Problem gelöst, aber es hat den iscroll "Snap" -Effekt deaktiviert. Die Lösung bestand darin "position:relative; z-index:1000;display:block", dem gesamten Container, der das Bildlaufelement enthält , CSS-Eigenschaften zuzuweisen, und es ist nicht erforderlich, untergeordneten Elementen translate3d zuzuweisen.

Yudarik
quelle
Ich habe diese Technik verwendet, um ein ähnliches Problem unter Android Chrome zu lösen. Das vertikale Scrollen schien besser zu funktionieren als beim Versuch, das translate3d-Update durchzuführen. In meinem Fall ist <body>Element, was ich zum Scrollen verwendet habe und eine vereinfachte Version funktioniert:body { position: relative; z-index: 0; }
BumbleB2na
1

Zur Zeit translate3dmöglicherweise nicht funktioniert, in diesen Fällen perspectivekann verwendet werden

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

Ich bin mir ziemlich sicher, dass ich das gerade gelöst habe mit:

overflow-y: auto;

(Vermutlich overflow: auto;würde es auch funktionieren, abhängig von Ihren Bedürfnissen.)

David Notik
quelle
Es hat nichts für mich getan, während die akzeptierte Antwort wahrscheinlich ein anderes Szenario darstellte
Tony
0

Es gibt Fälle, in denen eine Drehung angewendet und / oder ein Z-Index verwendet wird.

Drehung : Eine vorhandene Deklaration -webkit-transformzum Drehen eines Elements reicht möglicherweise nicht aus, um auch das Erscheinungsbildproblem (wie -webkit-transform: rotate(-45deg)) zu lösen . In diesem Fall können Sie -webkit-transform: translateZ(0px) rotateZ(-45deg)als Trick verwenden ( beachten Sie die Drehung Z ).

Z-Index : Zusammen mit der Rotation können Sie eine positive z-indexEigenschaft definieren , wie z z-index: 42. Die oben unter "Rotation" beschriebenen Schritte waren in meinem Fall ausreichend, um das Problem auch bei leerem zu beheben translateZ(0px). Ich vermute jedoch, dass der Z-Index in diesem Fall das Verschwinden und Wiederauftauchen überhaupt erst verursacht haben könnte . In jedem Fall muss die z-index: 42Immobilie erhalten bleiben - -webkit-transform: translateZ(42px)nur reicht nicht aus.

Stefan Zurfluh
quelle
0

Dies ist ein sehr häufiges Problem, mit dem Entwickler konfrontiert sind, und das hauptsächlich auf die Safari'sEigenschaft zurückzuführen ist, Elemente, die als definiert sind, nicht neu zu erstellen position : fixed.

Ändern Sie also entweder die Positionseigenschaft oder es muss ein Hack angewendet werden, wie in anderen Antworten erwähnt.

Link1

Link2

Arqam
quelle
0

In meinem Fall (einer iOS Phonegap-App) konnte das Problem durch Anwenden von translate3d auf relative untergeordnete Elemente nicht behoben werden. Mein scrollbares Element hatte keine festgelegte Höhe, da es absolut positioniert war und ich die oberen und unteren Positionen definierte. Was es für mich behoben hat, war das Hinzufügen einer Mindesthöhe (von 100px).

b4tch
quelle
0

Ich hatte das gleiche Problem mit einer älteren Version von Fancybox. Ein Upgrade auf v3 löst Ihr Problem ODER Sie können einfach hinzufügen:

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

Ich habe dieses Problem in einem Framework7 & Cordova-Projekt festgestellt. Ich habe alle oben genannten Lösungen ausprobiert. Sie haben mein Problem nicht gelöst.

In meinem Fall habe ich mehr als 10 CSS-Animationen auf derselben Seite mit unendlicher Rotation (Transformation) verwendet. Ich musste die Animationen entfernen. Es ist jetzt in Ordnung, da einige visuelle Merkmale fehlen.

Wenn die oben genannten Lösungen Ihnen nicht helfen, können Sie einige Animationen entfernen.

yavuzkirez
quelle
0

Der -webkit-transform: translate3d(0, 0, 0);Trick hat bei mir nicht funktioniert. In meinem Fall hatte ich einen Elternteil eingestellt auf:

// parent
height: 100vh;

Ändern Sie das zu:

height: auto;
min-height: 100vh;

Das Problem wurde behoben, falls jemand anderes mit der gleichen Situation konfrontiert ist.

Funador
quelle
0

In meinem Fall hat CSS das Problem nicht behoben. Ich habe das Problem bei der Verwendung von jQuery festgestellt, bei dem eine Schaltfläche erneut gerendert wurde.

$("#myButton").html("text")

Versuche dies

$("#myButton").html("<span>text</span>")
Josh Stovall
quelle