No IOS8 Safari, há um novo bug com a posição corrigida.
Se você focar em uma área de texto que está em um painel fixo, o safari irá rolar você para o final da página.
Isso torna impossível trabalhar com todos os tipos de IUs, já que você não tem como inserir texto em áreas de texto sem rolar sua página totalmente para baixo e perder seu lugar.
Existe alguma maneira de contornar esse bug de forma limpa?
#a {
height: 10000px;
background: linear-gradient(red, blue);
}
#b {
position: fixed;
bottom: 20px;
left: 10%;
width: 100%;
height: 300px;
}
textarea {
width: 80%;
height: 300px;
}
<html>
<body>
<div id="a"></div>
<div id="b"><textarea></textarea></div>
</body>
</html>
Respostas:
Com base nessa boa análise desse problema, usei os elementos
html
ebody
em css:Acho que está funcionando muito bem para mim.
fonte
transform: translateZ(0);
em stackoverflow.com/questions/7808110/…A melhor solução que eu poderia encontrar é mudar para o uso
position: absolute;
de foco e calcular a posição em que estava quando estava usandoposition: fixed;
. O truque é que ofocus
evento dispara tarde demais, entãotouchstart
deve ser usado.A solução nesta resposta imita o comportamento correto que tínhamos no iOS 7 muito de perto.
Requisitos:
O
body
elemento deve ter posicionamento para garantir o posicionamento correto quando o elemento muda para o posicionamento absoluto.O código ( exemplo ao vivo ):
O código a seguir é um exemplo básico para o caso de teste fornecido e pode ser adaptado para seu caso de uso específico.
Aqui está o mesmo código sem o hack para comparação .
Embargo:
Se o
position: fixed;
elemento tiver qualquer outro elemento pai com posicionamento além dissobody
, alternar paraposition: absolute;
pode ter um comportamento inesperado. Devido à naturezaposition: fixed;
disso, provavelmente não é um problema importante, uma vez que o aninhamento de tais elementos não é comum.Recomendações:
Embora o uso do
touchstart
evento filtre a maioria dos ambientes de desktop, você provavelmente desejará usar o sniffing de agente de usuário para que este código seja executado apenas no iOS 8 quebrado, e não em outros dispositivos, como Android e versões mais antigas do iOS. Infelizmente, ainda não sabemos quando a Apple irá corrigir esse problema no iOS, mas eu ficaria surpreso se não fosse corrigido na próxima versão principal.fonte
Encontrei um método que funciona sem a necessidade de mudar para a posição absoluta!
Código totalmente não comentado
Quebrando isso
Primeiro, você precisa ter o campo de entrada fixo no topo da página no HTML (é um elemento fixo, portanto, semanticamente deve fazer sentido tê-lo próximo ao topo de qualquer maneira):
Então você precisa salvar a posição de rolagem atual em variáveis globais:
Então você precisa encontrar uma maneira de detectar dispositivos iOS para que não afete coisas que não precisam de correção (função retirada de https://stackoverflow.com/a/9039885/1611058 )
Agora que temos tudo de que precisamos, aqui está a correção :)
fonte
Consegui consertar isso para entradas selecionadas adicionando um ouvinte de evento aos elementos de seleção necessários e, em seguida, rolando por um deslocamento de um pixel quando a seleção em questão ganha o foco.
Esta não é necessariamente uma boa solução, mas é muito mais simples e confiável do que as outras respostas que vi aqui. O navegador parece renderizar / recalcular a posição: fixa; atributo baseado no deslocamento fornecido na função window.scrollBy ().
fonte
Assim como Mark Ryan Sallee sugeriu, descobri que alterar dinamicamente a altura e o estouro do meu elemento de fundo é a chave - isso não dá ao Safari nada para percorrer.
Assim, após o término da animação de abertura do modal, altere o estilo do fundo:
Ao fechar o modal, altere-o de volta:
Embora outras respostas sejam úteis em contextos mais simples, meu DOM era muito complicado (graças ao SharePoint) para usar a troca de posição absoluta / fixa.
fonte
De forma limpa? não.
Recentemente, tive esse problema com um campo de pesquisa fixo em um cabeçalho fixo, o melhor que você pode fazer no momento é manter a posição de rolagem em uma variável o tempo todo e, após a seleção, tornar a posição do elemento fixo absoluta em vez de fixa com um topo posição com base na posição de rolagem do documento.
No entanto, isso é muito feio e ainda resulta em algumas rolagens estranhas para frente e para trás antes de pousar no lugar certo, mas é o mais próximo que pude chegar.
Qualquer outra solução envolveria substituir a mecânica de rolagem padrão do navegador.
fonte
Isso agora está corrigido no iOS 10.3!
Hacks não devem mais ser necessários.
fonte
Não lidei com esse bug em particular, mas talvez coloque um estouro: oculto; no corpo quando a área de texto está visível (ou apenas ativa, dependendo do seu design). Isso pode ter o efeito de não deixar o navegador "para baixo" para onde rolar.
fonte
Uma possível solução seria substituir o campo de entrada.
codepen
fonte
Nenhuma dessas soluções funcionou para mim porque meu DOM é complicado e eu tenho páginas dinâmicas de rolagem infinita, então tive que criar minhas próprias.
Plano de fundo: estou usando um cabeçalho fixo e um elemento mais abaixo que fica abaixo dele quando o usuário rola para baixo. Este elemento possui um campo de entrada de pesquisa. Além disso, adicionei páginas dinâmicas durante a rolagem para frente e para trás.
Problema: No iOS, sempre que o usuário clicava na entrada no elemento fixo, o navegador rolava até o topo da página. Isso não apenas causou um comportamento indesejado, mas também acionou minha adição dinâmica de página no topo da página.
Solução esperada: nenhuma rolagem no iOS (nenhuma) quando o usuário clica na entrada no elemento aderente.
Solução:
Requisitos: JQuery mobile é necessário para que as funções startsroll e stopscroll funcionem.
Debounce está incluído para suavizar qualquer lag criado pelo elemento aderente.
Testado em iOS10.
fonte
Acabei de pular sobre algo assim ontem, definindo a altura de #a para a altura máxima visível (a altura do corpo era no meu caso) quando #b está visível
ex:
ps: desculpe pelo último exemplo, só percebi que era necessário.
fonte
Tive o problema, as linhas de código abaixo resolveram para mim -
fonte