Прокрутка iPad Safari приводит к исчезновению и повторному появлению HTML-элементов с задержкой

165

В настоящее время я занимаюсь разработкой веб-приложения с использованием html5 и jQuery для iPad Safari. Я столкнулся с проблемой, когда большие области прокрутки приводят к тому, что элементы, находящиеся вне экрана, появляются после задержки, когда я прокручиваю их вниз.

Под этим я подразумеваю, что если у меня есть ряд изображений (или даже div с градиентом), который находится за кадром, при прокрутке вниз (или вверх) к нему ожидаемое поведение элемента будет отображаться на экране как Я прокручиваю до этого.

Тем не менее, я вижу, что элемент не появляется пока я не уберу палец с экрана, и скроллер не завершит все свои анимации.

Это вызывает у меня очень заметную проблему, заставляя все это выглядеть нестабильно, хотя это не так. Я предполагаю, что iPad Safari пытается что-то сделать, чтобы сохранить память. Есть ли способ, которым я могу предотвратить эту изменчивость? Кроме того, я был бы также признателен, если бы кто-нибудь смог пролить свет на то, что на самом деле пытается сделать iPad Safari.

codeBearer
источник
Эта проблема / решение помогло мне решить проблему с версией CSS Transforms jPanelMenu 1.3, которая превращала все на моем сайте, пока я не добавил вышеупомянутый фрагмент.
75-й тромбон
2
Использование *: not (html) будет применять translate3d ко всем другим аспектам вашего сайта, и я не рекомендую. Это приведет к тому, что изображения во вкладках исчезнут при прокрутке вниз и т. Д., Ошибки, которые вы могли бы использовать для просмотра только ваших 3d-изображений, теперь будут присутствовать в других аспектах вашего сайта.
Джонатан Тонге
1
У меня было несколько <svg>элементов, которые демонстрировали похожее отложенное рисование / рендеринг. К сожалению, это *:not(html) { ... }привело к всевозможным странным действиям, которые, как указывал @JonathanTonge, могут произойти. Тем не менее, выбор только <svg>элементов и их использование, translate3d(0, 0, 0,);похоже, решили мои проблемы с прокруткой.
Зефир Мэйс
За исключением очень конкретных случаев использования, это мусор. Действительно портит макеты, которые зависят от элементов абсолютного положения.
Стоути
2
Пожалуйста, отправляйте ответы как ответы, а не «РЕДАКТИРУЙТЕ» в вашем вопросе. Я знаю, что вам больше нравится ваш ответ, и это нормально, но StackOverflow имеет формат вопросов и ответов, который лучше всего работает, когда Q отличаются от A.
Слипп Д. Томпсон

Ответы:

184

Вам нужно обмануть браузер, чтобы использовать аппаратное ускорение более эффективно. Вы можете сделать это с помощью пустого трехмерного преобразования:

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

В частности, это понадобится для дочерних элементов, у которых есть position:relative;объявление (или просто сделайте все возможное и сделайте это со всеми дочерними элементами).

Не гарантированное исправление, но довольно успешно в большинстве случаев.

Наконечник шляпы: https://web.archive.org/web/20131005175118/http://cantina.co/2012/03/06/ios-5-native-scrolling-grins-and-gothcas/

Колин Уильямс
источник
3
Я тоже это попробовал. К сожалению, добавление translate3d обрезает элементы, которые раньше отображались правильно. Мне также нужно было аппаратное ускорение для пары объектов, которые были вне экрана и должны были быть анимированы, чтобы «летать» на экране. Я использовал jQuery's animate (), который был очень медленным. Я переключился на использование аппаратного ускорения. Хотя это ускорило анимацию, оно дало ошибочные результаты, в том смысле, что некоторые дочерние элементы родительского (анимирующего) элемента div были обрезаны. Этого не происходило, когда я использовал animate ().
codeBearer
1
@ Колин Уильямс, ты только что сделал мой день! : D
Лука
9
Вау, это ужасно, но эффективно. Спасибо.
Тим Даун
1
Золотая звезда! Я добавил его ко всем своим элементам li в прокручиваемом элементе div. Пуф. Работал.
Брайан Джонсон
68

Это полный ответ на мой вопрос. Первоначально я пометил ответ @Colin Williams как правильный ответ, поскольку он помог мне найти полное решение. Член сообщества @Slipp D. Thompson отредактировал мой вопрос после того, как примерно через 2,5 года я его задал, и сказал, что я злоупотребляю форматом вопросов и ответов SO. Он также сказал мне отдельно опубликовать это как ответ. Итак, вот полный ответ, который решил мою проблему:

@ Колин Уильямс, спасибо! Ваш ответ и статья, на которую вы ссылались, дали мне шанс попробовать что-то с CSS.

Итак, я использовал translate3d раньше. Это дало нежелательные результаты. По сути, это будет откалывать и не отображать элементы, которые были за кадром, пока я не взаимодействовал с ними. Так что, в основном в альбомной ориентации, половина моего сайта, который был за кадром, не отображалась. Это веб-приложение для iPad, благодаря которому я был в затруднительном положении.

Применение translate3d к относительно позиционированным элементам решило проблему для этих элементов, но другие элементы прекратили рендеринг после выхода за экран. Элементы, с которыми я не мог взаимодействовать (художественные работы), никогда больше не будут отображаться, если я не перезагрузил страницу.

Полное решение:

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

Теперь, хотя это может быть не самое «эффективное» решение, оно было единственным, которое работает. Mobile Safari не отображает элементы, которые находятся за пределами экрана, или иногда отображаются с ошибками при использовании -webkit-overflow-scrolling: touch. Если translate3d не будет применен ко всем другим элементам, которые могут выйти за пределы экрана из-за этой прокрутки, эти элементы будут отключены после прокрутки.

Итак, еще раз спасибо, и надеюсь, что это поможет какой-то другой потерянной душе. Это, безусловно, помогло мне большое время!

codeBearer
источник
2
Вот это да. Спасибо за это. Это спасло меня от головной боли в приложении PhoneGap / Cordova. В моем случае мне пришлось изменить *:not(html)наbody *
Anon
9
просто применяя -webkit-transform: translate3d(0, 0, 0); к проблеме элемента работало для меня. В моем случае я использовал ScrollMagic
fidev
Ничто из этого не сработало для меня. Как только я прокручиваю вниз до определенной точки, невидимый материал над окном становится грязным, а также некоторые элементы в области просмотра. Я замечаю очень легкую, но безошибочную «тряску» во время прокрутки, после которой элементы скрываются. (То есть: плавное - нервное - плавное поведение, как будто оно икнет во время прокрутки.) Это на iPad.
cbmtrx
Кстати, я только что обнаружил, что на iPad Air 2, когда определенный экранный элемент (в данном случае навигационная панель) выходит за пределы экрана, устройство «перезагружает» этот блок - только с использованием большой версии, а не оригинальной средней. что страница загружена. Что за ...
cbmtrx
В случае, если кто-то испытывает ту же причуду, что и я - немного отличается от того, что описано на этой странице - я обнаружил, что использование $(window).width()вместо window.innerWidthJQuery имеет все значение для iOS. Кто знает.
cbmtrx
13

Ориентация на все элементы, кроме HTML: *:not(html) в моем случае вызвала проблемы с другими элементами. Это изменило контекст стека, вызывая разрыв некоторого z-индекса.

Мы должны лучше попытаться выбрать правильный элемент и применить-webkit-transform: translate3d(0,0,0) его только к нему.

Изменить: иногда translate3D(0,0,0)это не работает, мы можем использовать следующий метод, ориентируясь на нужный элемент:

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

// ios redraw fix
animation: redraw 1s linear infinite;
Гийом Готье
источник
Я столкнулся с той же проблемой. Вы можете использовать body *селектор вместо *:not(html). Это решит вашу проблему.
Кунал
Престижность за предложение нацелиться на правильные элементы, а не загрязнять все с помощью *
Maciek Rek
7

Когда translate3d не работает, попробуйте добавить перспективу. У меня всегда работает

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

Фелипе Лима
источник
Holy C $ # @, наконец, решение для угловых / ионных. -webkit-perspective: 1000;
lilbiscuit
Ах, спас мой день. +1 для вас;)
Омар Бахир
Это привело к краху моего браузера iOS.
Андреас Рихтер
-webkit-perspective: 1000;сделал это для меня - спасибо
jHilscher
2

Добавление -webkit-transform: translate3d(0,0,0)к элементу статически не работает для меня.

Я применяю это свойство динамически. Например, когда страница прокручивается, я устанавливаю -webkit-transform: translate3d(0,0,0)элемент. Затем после небольшой задержки я сбрасываю это свойство, то есть -webkit-transform: none этот подход, похоже, работает.

Спасибо, @Colin Уильямс, что указали мне в правильном направлении.

Александр Полещук
источник
Этот намек очень помог мне, так как эти стили вызывают нежелательные побочные эффекты, которых я обычно хочу избежать. Поэтому я использую события touchstart / touchend для их добавления и удаления. Спасибо!
Windwalker
1

У меня была такая же проблема с iscroll 4.2.5 на ios7. Весь элемент прокрутки просто исчезнет. Я попытался добавить, translate3d(0,0,0)как было предложено здесь, это решило проблему, но отключил эффект «привязки» iscroll. Решение пришло с предоставлением "position:relative; z-index:1000;display:block"свойств css всему контейнеру, который содержит элемент прокрутки, и нет необходимости передавать translate3d дочерним элементам.

yudarik
источник
Я использовал эту технику для решения аналогичной проблемы на Android Chrome. Вертикальная прокрутка, казалось, работала лучше, чем когда я пытался исправить translate3d. В моем случае <body>элемент - это то, что я использовал для прокрутки, и сработала упрощенная версия:body { position: relative; z-index: 0; }
BumbleB2na
1

Время translate3dможет не работать, в этих случаях perspectiveможно использовать

transform: translate3d(0, 0, 0);
-webkit-transform: translate3d(0, 0, 0);
perspective: 1000;
-webkit-perspective: 1000;
Нидин Джозеф
источник
0

Я чертовски уверен, что только что решил это с:

overflow-y: auto;

(Предположительно просто overflow: auto;будет работать в зависимости от ваших потребностей.)

Дэвид Нотик
источник
Это ничего не сделало для меня, тогда как принятый ответ сделал, вероятно, другой сценарий
Тони
0

Есть случаи, когда применяется вращение и / или Z-индекс .

Вращение : существующее объявление -webkit-transformповорота элемента может быть недостаточно для решения проблемы внешнего вида (например -webkit-transform: rotate(-45deg)). В этом случае вы можете использовать -webkit-transform: translateZ(0px) rotateZ(-45deg)как трюк ( обратите внимание на поворот Z ).

Индекс Z : вместе с вращением вы можете определить положительное z-indexсвойство, например z-index: 42. Вышеописанных шагов, описанных в разделе «Вращение», в моем случае было достаточно, чтобы решить проблему, даже с пустым translateZ(0px). Я подозреваю, однако, что индекс Z в этом случае, возможно, вызвал исчезновение и повторное появление в первую очередь. В любом случае z-index: 42собственность должна быть сохранена - -webkit-transform: translateZ(42px)только недостаточно.

Стефан Цурфлух
источник
0

Это очень распространенная проблема, с которой сталкиваются разработчики, и это в основном из-за Safari'sсвойства не воссоздания элементов, определенных как position : fixed.

Так что либо измените свойство position, либо нужно применить какой-то взлом, как указано в других ответах.

Link1

Link2

Аркам
источник
0

В моем случае (приложение iOS Phonegap) применение translate3d к относительным дочерним элементам не решило проблему. У моего прокручиваемого элемента не было заданной высоты, поскольку он был абсолютно позиционирован, и я определял верхнюю и нижнюю позиции. Для меня это было добавлением минимальной высоты (100 пикселей).

b4tch
источник
0

У меня была та же проблема с использованием более старой версии Fancybox. Обновление до v3 решит вашу проблему, ИЛИ вы можете просто добавить:

html, body {
    -webkit-overflow-scrolling : touch !important;
    overflow: auto !important;
    height: 100% !important;
}
Адам Тоухоу
источник
0

Я столкнулся с этой проблемой в проекте Framework7 & Cordova. Я перепробовал все решения выше. Они не решили мою проблему.

В моем случае я использовал 10+ CSS анимаций на одной странице с бесконечным вращением (трансформация). Я должен был удалить анимацию. Теперь все в порядке с отсутствием некоторых визуальных функций.

Если приведенные выше решения не помогут вам, вы можете начать удалять некоторые анимации.

yavuzkirez
источник
0

-webkit-transform: translate3d(0, 0, 0);трюк не работает для меня. В моем случае я установил для родителя:

// parent
height: 100vh;

Меняя это на:

height: auto;
min-height: 100vh;

Решил проблему на случай, если кто-то еще столкнется с такой же ситуацией.

funador
источник
0

В моем случае CSS не устранил проблему. Я заметил проблему при использовании повторного рендеринга кнопки jQuery.

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

Попробуй это

$("#myButton").html("<span>text</span>")
Джош Стовалл
источник