Przewijanie iPada Safari powoduje, że elementy HTML znikają i pojawiają się ponownie z opóźnieniem


165

Obecnie tworzę aplikację internetową przy użyciu html5 i jQuery dla iPad Safari. Mam problem, w którym duże obszary przewijania powodują, że elementy poza ekranem pojawiają się z opóźnieniem, gdy przewijam je w dół.

Rozumiem przez to, że jeśli mam wiersz obrazów (lub nawet element div z gradientem), który jest poza ekranem, kiedy przewijam do niego w dół (lub w górę), oczekiwanym zachowaniem elementu jest pojawienie się na ekranie jako Przewijam do niego.

Jednak widzę, że element nie pojawia się, dopóki nie zdejmę palca z ekranu i rolka nie zakończy wszystkich animacji.

Jest to dla mnie bardzo zauważalny problem, przez co całość wygląda na nierówną, chociaż tak nie jest. Domyślam się, że iPad Safari próbuje coś zrobić, aby zaoszczędzić pamięć. Czy jest jakiś sposób, w jaki mógłbym zapobiec wystąpieniu tej niepewności? Dodatkowo byłbym wdzięczny, gdyby ktoś mógł rzucić światło na to, co tak naprawdę próbuje zrobić iPad Safari.


Ten problem / rozwiązanie pomogło mi naprawić problem z wersją jPanelMenu 1.3 CSS Transforms, która sprawiała, że ​​wszystko na mojej stronie było niewidoczne, dopóki nie dodałem powyższego fragmentu.
75th Trombone

2
Użycie *: not (html) spowoduje zastosowanie translate3d do wszystkich innych aspektów Twojej witryny i nie polecam. Spowoduje to, że obrazy na kartach znikną podczas przewijania w dół, itp., Błędy, które możesz przyzwyczaić do oglądania tylko na obrazach 3D, będą teraz obecne w innych aspektach Twojej witryny.
Jonathan Tonge,

1
Miałem kilka <svg>elementów, które wykazywały podobne opóźnione rysowanie / renderowanie. Niestety, *:not(html) { ... }doprowadziło to do różnego rodzaju dziwnych zachowań, jak zauważył @JonathanTonge, które mogą wystąpić. Wydaje się jednak, że wybranie tylko <svg>elementów i użycie translate3d(0, 0, 0,);rozwiązało moje problemy z przewijaniem.
Zephyr Mays

Z wyjątkiem bardzo specyficznych przypadków użycia, to śmieci. Naprawdę psuje układy, które zależą od elementów pozycji bezwzględnej.
Stoutie

2
Prosimy zamieszczać odpowiedzi jako odpowiedzi, a nie „EDYTUJ” w swoim pytaniu. Wiem, że najbardziej lubisz swoją odpowiedź i to dobrze, ale StackOverflow ma format pytań i odpowiedzi, który działa najlepiej, gdy pytania są różne od liter „A”.
Slipp D. Thompson

Odpowiedzi:


184

Musisz oszukać przeglądarkę, aby efektywniej wykorzystywała akcelerację sprzętową. Możesz to zrobić za pomocą pustej transformacji 3D:

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

W szczególności będziesz tego potrzebować na elementach podrzędnych, które mają position:relative;deklarację (lub po prostu idź na całość i zrób to dla wszystkich elementów podrzędnych).

Nie jest to gwarantowana poprawka, ale przez większość czasu dość skuteczna.

Wskazówka dotycząca kapelusza: https://web.archive.org/web/20131005175118/http://cantina.co/2012/03/06/ios-5-native-scrolling-grins-and-gothcas/


3
Ja też tego próbowałem. Niestety dodanie translate3d to odcinanie elementów, które wcześniej były poprawnie wyświetlane. Potrzebowałem również akceleracji sprzętowej dla kilku obiektów, które były poza ekranem i musiały być animowane, aby „wlecieć” na ekran. Używałem animate () jQuery, który był bardzo wolny. Przerzuciłem się na akcelerację sprzętową. Chociaż przyspieszyło to animację, dało to błędne wyniki, w tym sensie, że niektóre elementy potomne nadrzędnego (animującego) elementu div zostały odcięte. Tak się nie działo, gdy używałem animate ().
codeBearer

1
@Colin Williams właśnie sprawiłeś, że mój dzień! : D
Łukasz

9
Wow, to jest okropne, ale skuteczne. Dziękuję Ci.
Tim Down


1
Złoty cholerny gwiazdor! Dodałem go do wszystkich moich elementów li w przewijalnym div. Poof. Pracował.
Bryan Johnson

68

To jest pełna odpowiedź na moje pytanie. Pierwotnie oznaczyłem odpowiedź @Colin Williams jako poprawną, ponieważ pomogła mi w znalezieniu kompletnego rozwiązania. Członek społeczności @Slipp D. Thompson zredagował moje pytanie po około 2,5 latach od zadawania go i powiedział, że nadużywam formatu pytań i odpowiedzi SO. Powiedział mi również, żebym osobno opublikował to jako odpowiedź. Oto pełna odpowiedź, która rozwiązała mój problem:

@Colin Williams, dziękuję! Twoja odpowiedź i artykuł, do którego dołączyłeś, dały mi wskazówkę do wypróbowania czegoś z CSS.

Tak więc wcześniej używałem translate3d. Dało to niepożądane rezultaty. Zasadniczo odcinał i NIE RENDERował elementy, które były poza ekranem, dopóki nie wejdę z nimi w interakcję. Zasadniczo w orientacji poziomej połowa mojej witryny, która była poza ekranem, nie była wyświetlana. To aplikacja internetowa na iPada, dzięki której byłem w naprawie.

Zastosowanie translate3d do względnie pozycjonowanych elementów rozwiązało problem dla tych elementów, ale inne elementy przestały renderować się poza ekranem. Elementy, z którymi nie mogłem wejść w interakcję (grafika), nigdy nie byłyby renderowane ponownie, chyba że ponownie załadowałem stronę.

Kompletne rozwiązanie:

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

Chociaż może to nie być najbardziej „wydajne” rozwiązanie, było to jedyne, które działało. Mobilne Safari nie renderuje elementów, które są poza ekranem lub czasami renderują się nieprawidłowo podczas używania -webkit-overflow-scrolling: touch. O ile translate3d nie zostanie zastosowane do wszystkich innych elementów, które mogą zniknąć z ekranu z powodu tego przewijania, elementy te zostaną odcięte po przewinięciu.

Więc jeszcze raz dziękuję i mam nadzieję, że pomoże to innej zagubionej duszy. To z pewnością bardzo mi pomogło!


2
Łał. Dzięki za to. Zaoszczędziło mi to ogromnej ilości bólu głowy w przypadku mojej aplikacji Phonegap / Cordova. W moim przypadku musiałem przesiąść się *:not(html)nabody *
anon

9
samo zastosowanie się -webkit-transform: translate3d(0, 0, 0);do elementu problemu zadziałało dla mnie. W moim przypadku użyłem ScrollMagic
fidev

Dla mnie też nic z tego nie zadziałało. Gdy tylko przewiniesz w dół do pewnego punktu, niewidoczne już elementy nad oknem zostaną zatrzaśnięte, a także niektóre elementy w widoku. Zauważam bardzo delikatny, ale nieomylny „wstrząs” podczas przewijania, po którym elementy są wężowane. (Tj. Gładkie - roztrzęsione - płynne zachowanie, jakby czkawka podczas przewijania). To jest na iPadzie.
cbmtrx

Swoją drogą, właśnie odkryłem, że na iPadzie Air 2, gdy określony element na ekranie (w tym przypadku pasek nawigacyjny) znika z ekranu, urządzenie „przeładowuje” ten blok - tylko przy użyciu dużej wersji, a nie oryginalnej średniej że strona została załadowana. Co do ...
cbmtrx

W przypadku, gdy ktoś doświadcza tej samej dziwności co ja - nieco różniącej się od tego, co opisano na tej stronie - stwierdziłem, że użycie $(window).width()zamiast window.innerWidthw jQuery zrobiło różnicę w iOS. Kto wie.
cbmtrx

13

Kierowanie na wszystkie elementy oprócz html: *:not(html) spowodowało problemy w innych elementach w moim przypadku. Zmodyfikował kontekst stosu, powodując zerwanie części indeksu z.

Powinniśmy lepiej spróbować skierować się na właściwy element i zastosować -webkit-transform: translate3d(0,0,0)tylko do niego.

Edycja: czasami translate3D(0,0,0)nie działa, możemy użyć następującej metody, celując w odpowiedni element:

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

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

Miałem ten sam problem. Możesz użyć body *selektora zamiast *:not(html). To rozwiąże Twój problem.
kunal

Brawa za sugestię, aby kierować się na właściwe elementy, zamiast zanieczyszczać wszystko *
Maciek Rek

7

Kiedy translate3d nie działa, spróbuj dodać perspektywę. U mnie to zawsze działa

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


święty c $ # @ wreszcie rozwiązanie dla kątowego / jonowego. -webkit-perspective: 1000;
lilbiscuit

Ahh uratował mi dzień. +1 dla ciebie;)
Omar Bahir

To spowodowało awarię przeglądarki iOS.
Andreas Richter,

-webkit-perspective: 1000;zrobił to dla mnie - dziękuję
jHilscher

2

Dodawanie -webkit-transform: translate3d(0,0,0) do elementu statycznie nie działa dla mnie.

Stosuję tę właściwość dynamicznie. Na przykład, kiedy strona jest przewijana, ustawiam -webkit-transform: translate3d(0,0,0)element. Następnie po krótkiej chwili resetuję tę właściwość, czyli takie -webkit-transform: none podejście wydaje się działać.

Dziękuję @Colin Williams za wskazanie mi właściwego kierunku.


Ta wskazówka bardzo mi pomogła, ponieważ te style mają pewne niepożądane skutki uboczne, których zwykle chcę uniknąć. Dlatego używam zdarzeń touchstart / touchend, aby je dodawać i usuwać. Dzięki!
Windwalker

1

Miałem ten sam problem z iscroll 4.2.5 na ios7. Cały element przewijania po prostu znika. Próbowałem dodać, translate3d(0,0,0)jak sugerowano tutaj, rozwiązało to problem, ale wyłączyło efekt „snap” iscroll. Rozwiązanie "position:relative; z-index:1000;display:block"polegało na nadaniu właściwości css całemu kontenerowi zawierającemu element scroll i nie ma potrzeby podawania translate3d elementom potomnym.


Użyłem tej techniki do rozwiązania podobnego problemu na Androidzie Chrome. Przewijanie w pionie wydawało się działać lepiej niż wtedy, gdy próbowałem naprawić translate3d. W moim przypadku <body>element jest tym, czego użyłem do przewijania i wersja uproszczona działała:body { position: relative; z-index: 0; }
BumbleB2na

1

Czasami translate3dmoże nie działać, w takich przypadkach perspectivemożna użyć

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

0

Jestem całkiem pewny, że właśnie to rozwiązałem:

overflow-y: auto;

(Prawdopodobnie po prostu overflow: auto;zadziałaby w zależności od twoich potrzeb.)


Nic to dla mnie nie dało, podczas gdy zaakceptowana odpowiedź oznaczała prawdopodobnie inny scenariusz
tony

0

Istnieją przypadki, w których stosuje się obrót i / lub używany jest indeks Z.

Rotacja : istniejąca deklaracja -webkit-transformobracania elementu może nie wystarczyć do rozwiązania problemu z wyglądem (np -webkit-transform: rotate(-45deg).). W tym przypadku możesz użyć -webkit-transform: translateZ(0px) rotateZ(-45deg)jako sztuczki ( pamiętaj o obracaniu Z ).

Indeks Z : Wraz z rotacją możesz zdefiniować z-indexwłaściwość dodatnią , taką jak z-index: 42. Powyższe kroki opisane w punkcie „Rotacja” były w moim przypadku wystarczające, aby rozwiązać problem, nawet z pustym translateZ(0px). Podejrzewam jednak, że indeks Z w tym przypadku mógł przede wszystkim spowodować zniknięcie i ponowne pojawienie się. W każdym razie z-index: 42nieruchomość musi być utrzymana - samo -webkit-transform: translateZ(42px)to nie wystarczy.


0

Jest to bardzo częsty problem, z którym borykają się deweloperzy, a wynika to głównie z Safari'swłaściwości braku odtwarzania elementów zdefiniowanych jako position : fixed.

Więc albo zmień właściwość pozycji, albo trzeba zastosować jakiś hack, jak wspomniano w innych odpowiedziach.

Link1

Link2


0

W moim przypadku (aplikacja iOS Phonegap) zastosowanie translate3d do względnych elementów potomnych nie rozwiązało problemu. Mój przewijalny element nie miał określonej wysokości, ponieważ był bezwzględnie ustawiony i definiowałem górną i dolną pozycję. Rozwiązaniem tego problemu było dodanie minimalnej wysokości (100 pikseli).


0

Miałem ten sam problem, używając starszej wersji Fancybox. Aktualizacja do wersji 3 rozwiąże Twój problem LUB możesz po prostu dodać:

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

0

Spotkałem się z tym problemem w projekcie Framework7 i Cordova. Wypróbowałem wszystkie powyższe rozwiązania. Nie rozwiązali mojego problemu.

W moim przypadku używałem ponad 10 animacji CSS na tej samej stronie z nieskończoną rotacją (transformacją). Musiałem usunąć animacje. Teraz jest w porządku z brakiem niektórych funkcji wizualnych.

Jeśli powyższe rozwiązania Ci nie pomogą, możesz przystąpić do eliminacji niektórych animacji.


0

ta -webkit-transform: translate3d(0, 0, 0);sztuczka nie zadziałała dla mnie. W moim przypadku ustawiłem rodzica, aby:

// parent
height: 100vh;

Zmieniam to na:

height: auto;
min-height: 100vh;

Rozwiązano problem na wypadek, gdyby ktoś inny znalazł się w takiej samej sytuacji.


0

W moim przypadku CSS nie rozwiązał problemu. Zauważyłem problem podczas ponownego renderowania przycisku jQuery.

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

Spróbuj tego

$("#myButton").html("<span>text</span>")
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.