iOS 5 posicionamento fixo e teclado virtual

138

Eu tenho um site para celular que tem uma div fixada na parte inferior da tela através da posição: fixo. Tudo funciona bem no iOS 5 (estou testando em um iPod Touch) até estar em uma página com um formulário. Quando toco em um campo de entrada e o teclado virtual aparece, de repente a posição fixa do meu div é perdida. A div agora rola com a página enquanto o teclado estiver visível. Quando clico em Concluído para fechar o teclado, a div reverte para sua posição na parte inferior da tela e obedece à posição: regra fixa.

Alguém mais experimentou esse tipo de comportamento? Isso é esperado? Obrigado.

jeffc
fonte
Sim, parece que a Apple não achou isso tão bom para o IOS5. Quaisquer elementos de posição fixa tornam-se relativos à página assim que o teclado virtual aparece. Provavelmente seria bom se os elementos revertessem para uma posição absoluta, pois isso não quebraria o layout. Infelizmente, o posicionamento real desses elementos é muito menos previsível. Eu tenho esse problema exato com meu cabeçalho fixo em [REDACTED]. Role a página e clique na caixa de pesquisa e clique em ... layout quebrado. Eu mesmo tentou corrigi-lo ao reverter para o posicionamento absoluto no evento de foco, que funciona, mas então eu los
John williams
2
Eu já tive esse mesmo problema. Alguém registrou um bug na Apple para resolver esse problema? Além disso, mais alguém viu esse comportamento continuar no iOS6?
Robert Hui
1
Estou com o mesmo problema com o iOS6.
Redtopia
24
O mesmo problema ainda parece existir no iOS7!
Ria Weyprecht 10/10
5
Não parece ser fixado no iOS 8 ...
contactmatt

Respostas:

49

Eu tive esse problema no meu aplicativo. Aqui está como eu estou trabalhando nisso:

input.on('focus', function(){
    header.css({position:'absolute'});
});
input.on('blur', function(){
    header.css({position:'fixed'});
});

Estou apenas rolando para o topo e posicionando-o ali, para que o usuário do iOS não note nada de estranho acontecendo. Coloque isso em alguma detecção do agente do usuário para que outros usuários não obtenham esse comportamento.

Nick Retallack
fonte
Literalmente, deparei com essa questão hoje e essa parecia a mais razoável, +1.
21413 Daniel
3
Isso funciona muito bem. Eu chamo isso apenas para dispositivos iOS: var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
Redtopia
8
Também removi $ (window) .scrollTop (0) ... Não acho que seja necessário e causou rolagem indesejada.
Redtopia
1
Ou simplesmente document.body.scrollTop = 0se você não estiver usando o jQuery e direcionando os navegadores mais recentes.
Langdon
Em formulários mais longos, a configuração de $(window).scrollTop(0);pode fazer com que a entrada focada seja movida para fora da tela, por exemplo, uma entrada mais abaixo na página ou se um iPhone estiver em retrato. Uma solução melhor é definir o foco e definir o header.css({position:'absolute',top:window.pageYOffset+'px'});desfoque header.css({position:'fixed',top:0});.
robocat
16

Eu tive um problema de ipad um pouco diferente, onde o teclado virtual empurrou minha janela de exibição para fora da tela. Depois que o usuário fechou o teclado virtual, minha janela de exibição ainda estava fora da tela. No meu caso, fiz algo como o seguinte:

var el = document.getElementById('someInputElement');
function blurInput() {
    window.scrollTo(0, 0);
}
el.addEventListener('blur', blurInput, false);
ds111
fonte
3
Não ajuda para mim :(
Dmitry
@Altaveron. Desculpe ouvir isso. Foi por um problema específico que eu estava tendo nos dispositivos iOS 6 e inferiores. Eu não revisitei desde então.
ds111
14

Este é o código que usamos para corrigir o problema com o ipad. Ele basicamente detecta discrepâncias entre deslocamento e posição de rolagem - o que significa que 'fixo' não está funcionando corretamente.

$(window).bind('scroll', function () {
    var $nav = $(".navbar")
    var scrollTop = $(window).scrollTop();
    var offsetTop = $nav.offset().top;

    if (Math.abs(scrollTop - offsetTop) > 1) {
        $nav.css('position', 'absolute');
        setTimeout(function(){
            $nav.css('position', 'fixed');
        }, 1);
    }
});
Escotilha
fonte
É do plugin jquery.timers. Você pode usar window.setTimeout.
Hatch
acionar esta mesma função no desfoque e no foco da entrada também ajudará.
Blowsie
Gênio - realmente cavar isso. Também marque +1 na sugestão de @ Blowsie de usar isso de foco e desfoque em vez de rolagem.
Skone
12

Os elementos fixos da posição simplesmente não atualizam sua posição quando o teclado está levantado. Descobri que, enganando o Safari a pensar que a página foi redimensionada, os elementos se reposicionam. Não é perfeito, mas pelo menos você não precisa se preocupar em mudar para 'position: absolute' e o rastreamento muda você mesmo.

O código a seguir apenas escuta quando é provável que o usuário esteja usando o teclado (devido ao foco de uma entrada) e, até ouvir um borrão, apenas escuta os eventos de rolagem e, em seguida, executa o truque de redimensionamento. Parece estar funcionando muito bem para mim até agora.

    var needsScrollUpdate = false;
    $(document).scroll(function(){
        if(needsScrollUpdate) {
            setTimeout(function() {
                $("body").css("height", "+=1").css("height", "-=1");
            }, 0);
        }
    });
    $("input, textarea").live("focus", function(e) {
        needsScrollUpdate = true;
    });

    $("input, textarea").live("blur", function(e) {
        needsScrollUpdate = false;
    });
Riley Dutton
fonte
Isso realmente não funcionou para mim no iPad. Acabei alterando a posição do rodapé fixo para relativo e o coloquei na parte inferior da página até que o evento de desfoque de entrada foi detectado quando alterei a posição novamente para fixo.
Akrikos
6
Não funciona mais, iOS tudo o bug provavelmente fixo fez este trabalho
Kevin
6

Caso alguém aconteça com esse tópico, como eu fiz enquanto pesquisava esse problema. Achei esse tópico útil para estimular meu pensamento sobre esse assunto.

Esta foi a minha solução para isso em um projeto recente. Você só precisa alterar o valor de "targetElem" para um seletor jQuery que representa seu cabeçalho.

if(navigator.userAgent.match(/iPad/i) != null){

var iOSKeyboardFix = {
      targetElem: $('#fooSelector'),
      init: (function(){
        $("input, textarea").on("focus", function() {
          iOSKeyboardFix.bind();
        });
      })(),

      bind: function(){
            $(document).on('scroll', iOSKeyboardFix.react);  
                 iOSKeyboardFix.react();      
      },

      react: function(){

              var offsetX  = iOSKeyboardFix.targetElem.offset().top;
              var scrollX = $(window).scrollTop();
              var changeX = offsetX - scrollX; 

              iOSKeyboardFix.targetElem.css({'position': 'fixed', 'top' : '-'+changeX+'px'});

              $('input, textarea').on('blur', iOSKeyboardFix.undo);

              $(document).on('touchstart', iOSKeyboardFix.undo);
      },

      undo: function(){

          iOSKeyboardFix.targetElem.removeAttr('style');
          document.activeElement.blur();
          $(document).off('scroll',iOSKeyboardFix.react);
          $(document).off('touchstart', iOSKeyboardFix.undo);
          $('input, textarea').off('blur', iOSKeyboardFix.undo);
      }
};

};

Há um pouco de atraso na correção, porque o iOS interrompe a manipulação do DOM enquanto está rolando, mas ele faz o truque ...

Jory Cunningham
fonte
Isso funciona muito bem até o iOS 7. Alguém mais teve problemas com o elemento sendo posicionado corretamente, mas desaparecendo?
precisa
@RonaKilmer Altere a initfunção para uma função regular (não é auto-invocável; está disparando muito cedo). Em seguida, ligue iOSKeyboardFix.init();pouco antes do final da ifdeclaração.
cfree
@ cfree Obrigado, eu implementei isso há algum tempo, mas esse não é o meu problema. Há algo mais acontecendo. Um dos meus elementos fixos desaparece quando é reposicionado. O outro não. Não posso culpar isso pelo reparo do teclado, pois não está acontecendo em todos os lugares. Também não vi que mais alguém tenha o mesmo problema, então terei que me aprofundar mais.
Rona Kilmer #
4

Nenhuma das outras respostas que encontrei para esse bug funcionou para mim. Consegui corrigi-lo simplesmente rolando a página de volta em 34px, a quantidade que o safari móvel rola para baixo. com jquery:

$('.search-form').on('focusin', function(){
    $(window).scrollTop($(window).scrollTop() + 34);
});

Obviamente, isso entrará em vigor em todos os navegadores, mas evita a quebra no iOS.

NealJMD
fonte
4

Esta questão é realmente irritante.

Eu combinei algumas das técnicas acima mencionadas e vim com isso:

$(document).on('focus', 'input, textarea', function() {
    $('.YOUR-FIXED-DIV').css('position', 'static');
});

$(document).on('blur', 'input, textarea', function() {
    setTimeout(function() {
        $('.YOUR-FIXED-DIV').css('position', 'fixed');
        $('body').css('height', '+=1').css('height', '-=1');
    }, 100);
});

Eu tenho duas barras de navegação fixas (cabeçalho e rodapé, usando o twitter bootstrap). Ambos agiram de forma estranha quando o teclado está ativado e estranho novamente depois que o teclado está desativado.

Com essa correção temporizada / atrasada, ela funciona. Ainda encontro uma falha de vez em quando, mas parece ser boa o suficiente para mostrá-la ao cliente.

Deixe-me saber se isso funciona para você. Caso contrário, poderemos encontrar outra coisa. Obrigado.

escapedcat
fonte
2
Parece que você não precisa desse tempo limite (pelo menos estava funcionando bem para mim sem) e, se também acontece em elementos selecionados, além de que esta solução funciona muito bem.
22813 Phillip Gooch
3

Eu estava enfrentando o mesmo problema com o iOS7. Os elementos fixos inferiores atrapalhariam minha visão e não o foco corretamente.

Tudo começou a funcionar quando adicionei essa metatag ao meu html.

<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,height=device-height" >

A parte que fez a diferença foi:

height=device-height

Espero que ajude alguém.

pasevin
fonte
Obrigado @pasevin. Isso corrigiu meu problema no iOS 9.3.2
stillatmylinux 24/16
3

Eu peguei a Jory Cunninghamresposta e a melhorei:

Em muitos casos, não é apenas um elemento que enlouquece, mas vários elementos de posição fixa; portanto, neste caso, targetElem deve ser um objeto jQuery que possui todos os elementos fixos que você deseja "consertar". Ho, isso parece fazer o teclado iOS desaparecer se você rolar ...

Desnecessário mencionar que você deve usar este evento DEPOIS do documento DOM readyou imediatamente antes da </body>tag de fechamento .

(function(){
    var targetElem = $('.fixedElement'), // or more than one
        $doc       = $(document),
        offsetY, scrollY, changeY;

    if( !targetElem.length || !navigator.userAgent.match(/iPhone|iPad|iPod/i) )
        return;

    $doc.on('focus.iOSKeyboardFix', 'input, textarea, [contenteditable]', bind);

    function bind(){
        $(window).on('scroll.iOSKeyboardFix', react);
        react();
    }

    function react(){
        offsetY = targetElem.offset().top;
        scrollY = $(window).scrollTop();
        changeY = offsetY - scrollY;

        targetElem.css({'top':'-'+ changeY +'px'});

        // Instead of the above, I personally just do:
        // targetElem.css('opacity', 0);

        $doc.on('blur.iOSKeyboardFix', 'input, textarea, [contenteditable]', unbind)
            .on('touchend.iOSKeyboardFix', unbind);
    }

    function unbind(){
        targetElem.removeAttr('style');
        document.activeElement.blur();

        $(window).off('scroll.iOSKeyboardFix');
        $doc.off('touchend.iOSKeyboardFix blur.iOSKeyboardFix');
    }
})();
vsync
fonte
2
desculpas @vsync, eu não tinha idéia que você era um 'chef'
Mike
Quando selecionar, o foco de entrada nesse cabeçalho de tempo está subindo (não visível). Quero corrigir a div do cabeçalho ao focar os arquivos de seleção e entrada. qualquer um por favor me ajude
VK Chikkadamalla
2

Eu tenho uma solução semelhante ao @NealJMD, exceto que a minha é executada apenas para iOS e determina corretamente o deslocamento da rolagem medindo o scollTop antes e depois da rolagem do teclado nativo, bem como usando setTimeout para permitir a rolagem nativa:

var $window = $(window);
var initialScroll = $window.scrollTop();
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
  setTimeout(function () {
    $window.scrollTop($window.scrollTop() + (initialScroll - $window.scrollTop()));
  }, 0);
}
ChrisWren
fonte
1

Corrigi a posição fixa do conteúdo do layout principal do Ipad desta maneira:

var mainHeight;
var main = $('.main');

// hack to detects the virtual keyboard close action and fix the layout bug of fixed elements not being re-flowed
function mainHeightChanged() {
    $('body').scrollTop(0);
}

window.setInterval(function () {
    if (mainHeight !== main.height())mainHeightChanged();
    mainHeight = main.height();
}, 100);
Brett
fonte
Isso funcionou muito bem para mim em uma complicada mixagem de diálogo da interface do usuário JQUery e teclado na tela que deixou meu layout na metade da tela quando o diálogo e o teclado são fechados ao mesmo tempo, embora com algumas edições: var main = $ (' body div '). first (); ... e ... função mainHeightChanged () {$ (superior) .scrollTop (0); }
Awerealis 14/11/2013
1
setInterval... realmente? é melhor apenas para ficar com o bug do que fazendo isso
vsync
1

Eu tive um problema semelhante ao @ ds111 s. Meu site foi pressionado pelo teclado, mas não desceu quando o teclado foi fechado.

Primeiro, tentei a solução @ ds111, mas eu tinha dois inputcampos. Obviamente, primeiro o teclado desaparece, depois o desfoque acontece (ou algo assim). Então o segundo inputestava embaixo do teclado, quando o foco mudou diretamente de uma entrada para a outra.

Além disso, o "salto para cima" não foi bom o suficiente para mim, pois a página inteira tem apenas o tamanho do ipad. Então eu fiz o pergaminho suave.

Finalmente, tive que anexar o ouvinte de eventos a todas as entradas, mesmo aquelas que estavam atualmente ocultas, daí o live.

No total, posso explicar o seguinte trecho de javascript como: Anexe o seguinte ouvinte de evento de desfoque ao atual e a todo o futuro inpute textarea(= live): aguarde um período de cortesia (= window.setTimeout(..., 10)) e role suavemente para o topo (= animate({scrollTop: 0}, ...)), mas apenas se "não houver teclado" mostrado "(= if($('input:focus, textarea:focus').length == 0)).

$('input, textarea').live('blur', function(event) {
    window.setTimeout(function() {
        if($('input:focus, textarea:focus').length == 0) {
            $("html, body").animate({ scrollTop: 0 }, 400);
        }
    }, 10)
})

Esteja ciente de que o período de carência (= 10) pode ser muito curto ou o teclado ainda pode ser exibido, embora não esteja inputou textareaesteja focado. Obviamente, se você quiser rolar mais rápido ou mais devagar, poderá ajustar a duração (= 400)

Raul Pinto
fonte
1

realmente trabalhou duro para encontrar essa solução alternativa, que em resumo procura eventos de foco e desfoque nas entradas e rolagem para alterar seletivamente o posicionamento da barra fixa quando os eventos acontecem. Isso é à prova de balas e abrange todos os casos (navegando com <>, rolagem, botão pronto). Nota id = "nav" é minha div de rodapé fixo. Você pode facilmente portar isso para js ou jquery padrão. Este é dojo para quem usa ferramentas elétricas ;-)

define (["dojo / ready", "dojo / query",], função (ready, query) {

ready(function(){

    /* This addresses the dreaded "fixed footer floating when focusing inputs and keybard is shown" on iphone 
     * 
     */
    if(navigator.userAgent.match(/iPhone/i)){
        var allInputs = query('input,textarea,select');
        var d = document, navEl = "nav";
        allInputs.on('focus', function(el){
             d.getElementById(navEl).style.position = "static";
        });

        var fixFooter = function(){
            if(d.activeElement.tagName == "BODY"){
                d.getElementById(navEl).style.position = "fixed";
            }
        };
        allInputs.on('blur', fixFooter);
        var b = d.body;
        b.addEventListener("touchend", fixFooter );
    }

});

}); // final define

httpete
fonte
Isso pode ser incrível ... portar para jQuery / js & reportará de volta. Como um aparte, soluções em opções de linguagem de script de nicho que exigem portar ou adicionar ferramentas não padrão a um projeto, previsivelmente, não serão consideradas universalmente úteis.
ericpeters0n
Isso não funcionará em todos os casos, pois isso o levará para a posição 'estática' do elemento, que pode estar a quilômetros de distância da posição original da entrada, especialmente se estiver em um contêiner fixo. Se o contêiner tiver uma overflow:hiddenregra, você não verá sua entrada como está agora fora da caixa.
James M. Lay
1

Este é um problema difícil de acertar. Você pode tentar ocultar o rodapé no foco do elemento de entrada e mostrar o desfoque, mas isso nem sempre é confiável no iOS. De vez em quando (uma vez em dez, digamos, no meu iPhone 4S), o evento de foco parece não disparar (ou talvez exista uma condição de corrida), e o rodapé não fica oculto.

Depois de muitas tentativas e erros, descobri esta solução interessante:

<head>
    ...various JS and CSS imports...
    <script type="text/javascript">
        document.write( '<style>#footer{visibility:hidden}@media(min-height:' + ($( window ).height() - 10) + 'px){#footer{visibility:visible}}</style>' );
    </script>
</head>

Essencialmente: use JavaScript para determinar a altura da janela do dispositivo e crie dinamicamente uma consulta de mídia CSS para ocultar o rodapé quando a altura da janela diminuir em 10 pixels. Como a abertura do teclado redimensiona a exibição do navegador, isso nunca falha no iOS. Por usar o mecanismo CSS em vez do JavaScript, é muito mais rápido e suave também!

Nota: eu achei o uso de 'visibilidade: oculto' menos problemático do que 'display: none' ou 'position: static', mas sua milhagem pode variar.

Richard Kennard
fonte
1
Pode ser necessário alternar entre altura e largura para corrigir isso nos modos retrato e paisagem.
Neil Monroe
1

Funciona para mim

if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
    $(document).on('focus', 'input, textarea', function() {
        $('header').css({'position':'static'});
    });
    $(document).on('blur', 'input, textarea', function() {
        $('header').css({'position':'fixed'});
    });
}
ShibinRagh
fonte
1

No nosso caso, isso se consertaria assim que o usuário rolar. Portanto, esta é a correção que estamos usando para simular uma rolagem blurem qualquer um inputou textarea:

$(document).on('blur', 'input, textarea', function () {
    setTimeout(function () {
        window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
    }, 0);
});
basarat
fonte
1

Minha resposta é que isso não pode ser feito.

Vejo 25 respostas, mas nenhuma funciona no meu caso. É por isso que o Yahoo e outras páginas ocultam o cabeçalho fixo quando o teclado está ligado. E o Bing torna a página inteira não rolável (overflow-y: oculto).

Os casos discutidos acima são diferentes, alguns têm problemas ao rolar, outros são focados ou desfocados. Alguns têm rodapé fixo ou cabeçalho. Agora não posso testar cada combinação, mas você pode perceber que isso não pode ser feito no seu caso.

Szalai Laci
fonte
Isso não responde à pergunta.
9105 neófito
4
Sim, já que a resposta é que não há solução.
Szalai Laci
0

Encontrei esta solução no Github.

https://github.com/Simbul/baker/issues/504#issuecomment-12821392

Verifique se você tem conteúdo rolável.

// put in your .js file
$(window).load(function(){
    window.scrollTo(0, 1);
});

// min-height set for scrollable content
<div id="wrap" style="min-height: 480px">
  // website goes here
</div>

A barra de endereço é dobrada como um bônus adicional.

Leigh Mackay
fonte
0

Caso alguém queira tentar isso. Eu consegui o seguinte trabalhando para mim em um rodapé fixo com um campo de entrada.

<script>
    $('document').ready(
        function() {
            if (navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)
                  || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/Windows Phone/i)) {
                var windowHeight = $(window).height();
                var documentHeight = $(document).height();

                $('#notes').live('focus', function() {
                    if (documentHeight > windowHeight) {
                        $('#controlsContainer').css({
                            position : 'absolute'
                        });
                        $("html, body").animate({
                            scrollTop : $(document).height()
                        }, 1);
                    }
                });
                $('#notes').live('blur', function() {
                    $('#controlsContainer').css({
                        position : 'fixed'
                    });
                    $("html, body").animate({
                        scrollTop : 0
                    }, 1);
                });
            }
        });
</script>
Bernard
fonte
0

Eu tenho o mesmo problema. Mas percebi que a posição fixa está apenas atrasada e não quebrada (pelo menos para mim). Aguarde de 5 a 10 segundos e veja se a div se ajusta de volta à parte inferior da tela. Eu acredito que não é um erro, mas uma resposta atrasada quando o teclado está aberto.

Philip
fonte
0

Eu tentei todas as abordagens desse segmento, mas se elas não ajudaram, foram ainda piores. No final, decidi forçar o dispositivo a perder o foco:

$(<selector to your input field>).focus(function(){
    var $this = $(this);
    if (<user agent target check>) {
        function removeFocus () {
            $(<selector to some different interactive element>).focus();
            $(window).off('resize', removeFocus);
        }
        $(window).on('resize', removeFocus);
    }
});

e funcionou como um encanto e corrigiu meu formulário de login fixo.

Por favor NOTA:

  1. O código JS acima é apenas para apresentar minha ideia. Para executar esse trecho, substitua valores entre chaves angulares (<>) por valores apropriados para sua situação.
  2. Este código foi projetado para trabalhar com jQuery v1.10.2
Anton Boritskiy
fonte
0

Esse ainda é um bug grande para qualquer página HTML com os Bootstrap Modals mais altos no iOS 8.3. Nenhuma das soluções propostas acima funcionou e, após ampliar o zoom em qualquer campo abaixo da dobra de um modal alto, o Mobile Safari e / ou o WkWebView moveriam os elementos fixos para o local da rolagem do corpo HTML, deixando-os desalinhados com o local onde realmente estavam. estabelecido.

Para solucionar o erro, adicione um ouvinte de evento a qualquer uma das suas entradas modais, como:

$(select.modal).blur(function(){
  $('body').scrollTop(0);
});

Suponho que isso funcione porque forçar a altura de rolagem do corpo HTML realinha a exibição real com a localização do iOS 8 WebView que espera que o conteúdo da div modal modal seja.

depthfirstdesigner
fonte
0

Se alguém estava procurando uma rota completamente diferente (como você não está nem mesmo tentando fixar essa div "rodapé" ao rolar, mas deseja que a div fique na parte inferior da página), basta definir a posição do rodapé como relativo.

Isso significa que, mesmo que o teclado virtual apareça no seu navegador móvel, seu rodapé permanecerá ancorado na parte inferior da página, sem tentar reagir ao show ou fechar o teclado virtual.

Obviamente, parece melhor no Safari se a posição estiver fixa e o rodapé seguir a página enquanto você rola para cima ou para baixo, mas devido a esse bug estranho no Chrome, acabamos mudando para apenas tornar o rodapé relativo.

Terry Bu
fonte
0

Nenhuma das soluções de rolagem parecia funcionar para mim. Em vez disso, o que funcionou é definir a posição do corpo como fixa enquanto o usuário estiver editando o texto e depois restaurá-lo para estático quando o usuário terminar. Isso evita que o safari role seu conteúdo para você. Você pode fazer isso no foco / desfoque do (s) elemento (s) (mostrado abaixo para um único elemento, mas pode ser para todas as entradas, áreas de texto) ou se um usuário estiver fazendo algo para começar a editar, como abrir um modal, você pode nessa ação (por exemplo, abrir / fechar modal).

$("#myInput").on("focus", function () {
    $("body").css("position", "fixed");
});

$("#myInput").on("blur", function () {
    $("body").css("position", "static");
});
Scott Semyan
fonte
0

iOS9 - mesmo problema.

TLDR - fonte do problema. Para solução, role para baixo

Eu tinha um formulário em um position:fixediframe com id = 'subscribe-popup-frame'

Conforme a pergunta original, no foco da entrada, o iframe iria para a parte superior do documento, em vez da parte superior da tela.

O mesmo problema não ocorreu no modo safari dev com o agente do usuário definido como um dispositivo de identificação. Parece que o problema é causado pelo teclado virtual do iOS quando ele aparece.

Eu obtive alguma visibilidade do que estava acontecendo registrando a posição do iframe (por exemplo $('#subscribe-popup-frame', window.parent.document).position()) e a partir daí pude ver que o iOS parecia estar definindo a posição do elemento para {top: -x, left: 0}quando o teclado virtual apareceu (ou seja, focado no elemento de entrada).

Então, minha solução foi pegar essa traquina -x, reverter o sinal e usar o jQuery para adicionar essa topposição de volta ao iframe. Se houver uma solução melhor, eu adoraria ouvi-la, mas depois de tentar uma dúzia de abordagens diferentes, foi a única que funcionou para mim.

Desvantagem: eu precisava definir um tempo limite de 500ms (talvez menos funcionasse, mas eu queria estar seguro) para garantir que eu capturasse o xvalor final depois que o iOS fizesse seu mal com a posição do elemento. Como resultado, a experiência é muito instável. . . mas pelo menos funciona

Solução

        var mobileInputReposition = function(){
             //if statement is optional, I wanted to restrict this script to mobile devices where the problem arose
            if(screen.width < 769){
                setTimeout(function(){
                    var parentFrame = $('#subscribe-popup-frame',window.parent.document);
                    var parentFramePosFull = parentFrame.position();
                    var parentFramePosFlip = parentFramePosFull['top'] * -1;
                    parentFrame.css({'position' : 'fixed', 'top' : parentFramePosFlip + 'px'});
                },500);
            }    
        }   

Em seguida, basta chamar mobileInputRepositionalgo como $('your-input-field).focus(function(){})e$('your-input-field).blur(function(){})

martellalex
fonte