A rolagem do iPad Safari faz com que os elementos HTML desapareçam e reapareçam com um atraso

165

Atualmente, estou desenvolvendo um aplicativo Web usando html5 e jQuery para iPad Safari. Estou com um problema no qual grandes áreas de rolagem fazem com que os elementos que estão fora da tela apareçam após um atraso quando eu os deslizo para baixo.

O que quero dizer com isso é que, se eu tiver uma linha de imagens (ou mesmo uma div com um gradiente) fora da tela, quando eu rolar para baixo (ou para cima), o comportamento esperado é que o elemento apareça na tela como Estou rolando para ele.

No entanto, o que estou vendo é que o elemento não aparece até eu levantar o dedo da tela e o scroller terminar todas as suas animações.

Isso está causando um problema super perceptível para mim, fazendo com que tudo pareça instável, embora não seja. Suponho que o iPad Safari esteja tentando fazer algo para economizar memória. Existe alguma maneira de impedir que isso aconteça. Além disso, também gostaria que alguém pudesse esclarecer o que o iPad Safari está realmente tentando fazer.

codeBearer
fonte
Esse problema / solução me ajudou a corrigir um problema com a versão jPanelMenu 1.3 CSS Transforms, que tornou tudo invisível no meu site até eu adicionar o snippet acima.
75th Trombone
2
O uso de *: not (html) aplicará o translate3d a todos os outros aspectos do seu site e eu não recomendo. Isso fará com que as imagens nas guias desapareçam à medida que você rola para baixo, etc. Os bugs que você pode usar para ver apenas as imagens em 3D agora estarão presentes em outros aspectos do seu site.
Jonathan Tonge
1
Eu tinha alguns <svg>elementos que exibiam desenho / renderização atrasada semelhante. Infelizmente, isso *:not(html) { ... }levou a todos os tipos de comportamentos estranhos, como o @JonathanTonge apontou que pode ocorrer. No entanto, selecionar apenas os <svg>elementos e usar translate3d(0, 0, 0,);parece ter resolvido meus problemas de rolagem.
precisa saber é o seguinte
Exceto em casos de uso muito específicos, isso é lixo. Realmente bagunça layouts que dependem de elementos de posição absolutos.
Stoutie
2
Poste as respostas como respostas, e não "EDITAR" na sua pergunta. Sei que você gosta mais da sua resposta, e isso é bom, mas o StackOverflow tem um formato de perguntas e respostas que funciona melhor quando os Qs são distintos dos A's.
Slipp D. Thompson

Respostas:

184

Você precisa enganar o navegador para usar a aceleração de hardware com mais eficiência. Você pode fazer isso com uma transformação 3d vazia:

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

Particularmente, você precisará disso em elementos filho que possuem uma position:relative;declaração (ou, apenas faça o possível e faça isso com todos os elementos filho).

Não é uma correção garantida, mas é bem-sucedida na maioria das vezes.

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

Colin Williams
fonte
3
Eu tentei isso também. Infelizmente, adicionar um translate3d está cortando elementos que estavam sendo exibidos corretamente antes. Eu também precisava de aceleração de hardware para alguns objetos que estavam fora da tela e precisavam ser animados para "voar" na tela. Eu estava usando o animate () do jQuery, que era super lento. Eu mudei para o uso de aceleração de hardware. Embora isso tenha acelerado a animação, ela produziu resultados irregulares, no sentido de que alguns dos elementos filhos da div principal (animação) foram cortados. Isso não estava acontecendo quando eu estava usando animate ().
precisa saber é o seguinte
1
@Colin Williams você acabou de fazer o meu dia! : D
Lucas
9
Uau, isso é horrível, mas eficaz. Obrigado.
Tim Baixo
1
Homem das estrelas de ouro! Adicionei a todos os meus elementos li em uma div rolável. Poof. Trabalhou.
Bryan Johnson
68

Esta é a resposta completa para minha pergunta. Inicialmente, eu marquei a resposta de @Colin Williams como a resposta correta, pois me ajudou a chegar à solução completa. Um membro da comunidade, Slipp D. Thompson editou minha pergunta, após cerca de 2,5 anos depois de ter feito a pergunta, e me disse que estava abusando do formato de perguntas e respostas da SO. Ele também me disse para postar isso separadamente como resposta. Então, aqui está a resposta completa que resolveu meu problema:

@ Colin Williams, obrigado! Sua resposta e o artigo ao qual você vinculou me deram uma chance de experimentar algo com CSS.

Então, eu estava usando o translate3d antes. Produziu resultados indesejados. Basicamente, ele cortaria e não renderizaria os elementos que estavam fora da tela, até que eu interagisse com eles. Então, basicamente, na orientação paisagem, metade do meu site que estava fora da tela não estava sendo mostrada. Este é um aplicativo da web para iPad, devido ao qual eu estava corrigido.

A aplicação de translate3d em elementos relativamente posicionados resolveu o problema desses elementos, mas outros elementos pararam de renderizar, uma vez fora da tela. Os elementos com os quais eu não conseguia interagir (arte) nunca renderizariam novamente, a menos que eu recarregasse a página.

A solução completa:

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

Agora, embora essa possa não ser a solução mais "eficiente", foi a única que funciona. O Mobile Safari não processa os elementos que estão fora da tela ou, às vezes, são processados ​​erraticamente ao usar -webkit-overflow-scrolling: touch. A menos que um translate3d seja aplicado a todos os outros elementos que possam ficar fora da tela devido a esse pergaminho, esses elementos serão cortados após a rolagem.

Então, obrigado novamente, e espero que isso ajude outra alma perdida. Isso certamente me ajudou muito!

codeBearer
fonte
2
Uau. Obrigado por isso. Isso me salvou uma enorme dor de cabeça no meu aplicativo phonegap / cordova. No meu caso, tive que mudar *:not(html)parabody *
anon
9
apenas aplicar -webkit-transform: translate3d(0, 0, 0);ao elemento problemático funcionou para mim. No meu caso, eu estava usando ScrollMagic
fidev 28/08
Nada disso funcionou para mim também. Assim que eu desço até um certo ponto, o material não mais visível acima da janela fica mungado, além de alguns elementos na janela de exibição. Percebo uma "sacudida" muito leve, mas inconfundível, enquanto está rolando, após o qual os elementos são mangados. (Ou seja: comportamento suave - nervoso - suave, como se estivesse soluçando durante a rolagem.) Isso acontece no iPad.
Cbmtrx
BTW, eu acabei de descobrir que em um iPad Air 2, quando um elemento específico da tela (uma barra de navegação, neste caso) sai da tela, o dispositivo "recarrega" esse bloco - apenas usando a versão grande, e não a mídia original com a qual a página foi carregada. O que o ...
Cbmtrx 10/11
Caso alguém esteja enfrentando a mesma estranheza que eu - um pouco diferente do que é descrito nesta página -, descobri que o uso em $(window).width()vez do window.innerWidthjQuery fazia toda a diferença para o iOS. Quem sabe.
Cbmtrx
13

Segmentar todos os elementos, exceto html: *:not(html) causou problemas em outros elementos no meu caso. Ele modificou o contexto de empilhamento, causando a quebra de algum z-index.

É melhor tentarmos direcionar o elemento certo e aplicar -webkit-transform: translate3d(0,0,0)apenas a ele.

Editar: às vezes translate3D(0,0,0)não funciona, podemos usar o seguinte método, visando o elemento certo:

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

// ios redraw fix
animation: redraw 1s linear infinite;
Guillaume Gautier
fonte
Eu estava enfrentando o mesmo problema. Você pode usar o body *seletor em vez de *:not(html). Isso resolverá o problema.
precisa saber é
Kudos para a sugestão para segmentar os elementos certos ao invés de poluir tudo com a *
Maciek Rek
7

Quando o translate3d não funcionar, tente adicionar perspectiva. Sempre funciona para mim

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
fonte
santo c $ # @ finalmente uma solução para angular / iônico. -webkit-perspective: 1000;
lilbiscuit
Ahh salvou meu dia. +1 para você;)
Omar Bahir 05/02
Isso fez meu navegador iOS travar.
Andreas Richter
-webkit-perspective: 1000;fez isso por mim - obrigado
jHilscher
2

Adicionar -webkit-transform: translate3d(0,0,0)estaticamente a um elemento não funciona para mim.

Eu aplico essa propriedade dinamicamente. Por exemplo, quando uma página é rolada, defino -webkit-transform: translate3d(0,0,0)um elemento. Depois de um pequeno atraso, redefino essa propriedade, ou seja, -webkit-transform: none Essa abordagem parece funcionar.

Obrigado, @Colin Williams, por me indicar a direção certa.

Alexander Poleschuk
fonte
Essa dica me ajudou muito, já que esses estilos trazem efeitos colaterais indesejados, geralmente quero evitar. Então, eu uso os eventos touchstart / touchend para adicioná-los e removê-los. Obrigado!
Windwalker
1

Eu tive o mesmo problema com o iscroll 4.2.5 no ios7. Todo o elemento de rolagem desaparece. Eu tentei adicionar translate3d(0,0,0)como foi sugerido aqui, ele resolveu o problema, mas desativou o efeito "snap" do iscroll. A solução veio ao fornecer "position:relative; z-index:1000;display:block"propriedades css para todo o contêiner que contém o elemento scroll e não é necessário atribuir translate3d a elementos filho.

yudarik
fonte
Eu usei essa técnica para resolver um problema semelhante no Android Chrome. A rolagem vertical parecia ter um desempenho melhor do que quando tentei a correção translate3d. No meu caso <body>elemento é o que eu usei para rolagem e uma versão simplificada funcionou:body { position: relative; z-index: 0; }
BumbleB2na
1

Às vezes translate3dpode não funcionar, nesses casos, perspectivepode ser usado

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

Tenho certeza que acabei de resolver isso com:

overflow-y: auto;

(Presumivelmente, overflow: auto;isso também funcionaria dependendo das suas necessidades.)

David Notik
fonte
Ele não fez nada para mim enquanto a resposta aceite o fez, provavelmente, um cenário diferente
tony
0

Há casos em que uma rotação é aplicada e / ou um índice Z é usado.

Rotação : Uma declaração existente -webkit-transformpara rotacionar um elemento também pode não ser suficiente para resolver o problema de aparência (como -webkit-transform: rotate(-45deg)). Nesse caso, você pode usar -webkit-transform: translateZ(0px) rotateZ(-45deg)como um truque ( lembre-se de girar Z ).

Índice Z : junto com a rotação, você pode definir uma z-indexpropriedade positiva , como z-index: 42. As etapas acima descritas em "Rotação" foram, no meu caso, suficientes para resolver o problema, mesmo com o vazio translateZ(0px). Suspeito, porém, que o índice Z nesse caso possa ter causado o desaparecimento e o reaparecimento em primeiro lugar. De qualquer forma, a z-index: 42propriedade precisa ser mantida - -webkit-transform: translateZ(42px)apenas não é suficiente.

Stefan Zurfluh
fonte
0

Esse é um problema muito comum enfrentado pelos desenvolvedores e deve-se principalmente à Safari'spropriedade de não recriar elementos definidos como position : fixed.

Portanto, altere a propriedade position ou algum hack deve ser aplicado conforme mencionado em outras respostas.

Link1

Link2

arqam
fonte
0

No meu caso (um aplicativo Phonegap para iOS), a aplicação de translate3d em elementos filhos relativos não resolveu o problema. Meu elemento rolável não tinha uma altura definida, pois estava absolutamente posicionado e eu estava definindo as posições superior e inferior. O que foi corrigido para mim foi adicionar uma altura mínima (de 100px).

b4tch
fonte
0

Eu tive o mesmo problema usando uma versão mais antiga do Fancybox. A atualização para a v3 resolverá o seu problema OU você pode simplesmente adicionar:

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

Eu enfrentei esse problema em um projeto Framework7 & Cordova. Eu tentei todas as soluções acima. Eles não resolveram o meu problema.

No meu caso, eu estava usando mais de 10 animações css na mesma página com rotação infinita (transformação). Eu tive que remover as animações. Está tudo bem agora com a falta de alguns recursos visuais.

Se as soluções acima não ajudarem, você pode começar a eliminar algumas animações.

yavuzkirez
fonte
0

o -webkit-transform: translate3d(0, 0, 0);truque não funcionou para mim. No meu caso, eu havia definido um pai para:

// parent
height: 100vh;

Alterando isso para:

height: auto;
min-height: 100vh;

Resolvido o problema no caso de alguém enfrentar a mesma situação.

funador
fonte
0

No meu caso, o CSS não corrigiu o problema. Percebi o problema ao usar o jQuery para renderizar novamente um botão.

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

Tente isto

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