138

I have a mobile website which has a div pinned to the bottom of the screen via position:fixed. All works fine in iOS 5 (I'm testing on an iPod Touch) until I'm on a page with a form. When I tap into an input field and the virtual keyboard appears, suddenly the fixed position of my div is lost. The div now scrolls with the page as long as the keyboard is visible. Once I click Done to close the keyboard, the div reverts to its position at the bottom of the screen and obeys the position:fixed rule.

Has anyone else experienced this sort of behavior? Is this expected? Thanks.

4

25 に答える 25

16

仮想キーボードがビューポートを画面外に押し出すという、わずかに異なる iPad の問題がありました。次に、ユーザーが仮想キーボードを閉じた後、ビューポートはまだ画面外にありました。私の場合、私は次のようなことをしました:

var el = document.getElementById('someInputElement');
function blurInput() {
    window.scrollTo(0, 0);
}
el.addEventListener('blur', blurInput, false);
于 2012-09-27T21:35:38.357 に答える
14

これは、iPad の問題を修正するために使用するコードです。基本的に、オフセットとスクロール位置の不一致を検出します。これは、「固定」が正しく機能していないことを意味します。

$(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);
    }
});
于 2013-02-05T11:14:54.230 に答える
12

位置固定要素は、キーボードが上がっているときに位置を更新しません。ただし、ページのサイズが変更されたと Safari に認識させることで、要素が再配置されることがわかりました。完璧ではありませんが、少なくとも 'position: absolute' に切り替えて変更を自分で追跡することについて心配する必要はありません。

次のコードは、ユーザーがキーボードを使用する可能性が高いとき (入力がフォーカスされているため) をリッスンし、ぼかしが聞こえるまで、スクロール イベントをリッスンしてからサイズ変更トリックを実行します。これまでのところ、私にとってはかなりうまくいっているようです。

    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;
    });
于 2012-02-05T20:45:22.420 に答える
6

この問題の調査中に私が行ったように、誰かがこのスレッドに遭遇した場合に備えて。このスレッドは、この問題に関する私の考えを刺激するのに役立ちました。

これは、最近のプロジェクトでの私の解決策でした。「targetElem」の値を、ヘッダーを表す jQuery セレクターに変更するだけです。

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);
      }
};

};

スクロール中にiOSがDOM操作を停止するため、修正が定着するのに少し遅れがありますが、うまくいきます...

于 2013-02-28T18:13:38.150 に答える
4

このバグに対して私が見つけた他の答えはどれもうまくいきませんでした。ページを 34px だけ上にスクロールするだけで修正できました。これは、モバイル サファリが下にスクロールする量です。jquery を使用:

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

これは明らかにすべてのブラウザーで有効になりますが、iOS での破損を防ぎます。

于 2012-08-30T06:39:53.877 に答える
4

iOS7でも同じ問題が発生していました。下部の固定要素は、私のビューを台無しにし、適切に焦点を合わせません。

このメタタグをhtmlに追加すると、すべてが機能し始めました。

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

違いを生んだ部分は次のとおりです。

height=device-height

それが誰かを助けることを願っています。

于 2014-08-17T02:05:31.427 に答える
4

この問題は本当に厄介です。

上記のテクニックのいくつかを組み合わせて、これを思いつきました:

$(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);
});

2 つの固定ナビゲーション バーがあります (ヘッダーとフッター、Twitter ブートストラップを使用)。どちらも、キーボードが上にあるときはおかしくなり、キーボードが下にあると再びおかしくなりました。

この時限/遅延修正により、機能します。今でもたまに不具合を見つけますが、クライアントに見せるには十分なようです。

これがうまくいくかどうか教えてください。そうでない場合は、何か他のものを見つけることができるかもしれません。ありがとう。

于 2013-07-03T10:01:03.213 に答える
3

私はJory Cunningham答えを取り、それを改善しました:

多くの場合、おかしくなるのは 1 つの要素だけではなく、複数の固定配置要素であるため、この場合、targetElem「修正」したいすべての固定要素を含む jQuery オブジェクトにする必要があります。ホー、これはスクロールすると iOS キーボードが消えてしまうようです...

言うまでもなく、このAFTERドキュメントイベントを使用するか、終了タグDOM readyの直前に使用する必要があります。</body>

(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');
    }
})();
于 2014-06-08T16:04:44.550 に答える
2

@NealJMD に似たソリューションがありますが、私の場合は iOS でのみ実行され、ネイティブ キーボード スクロールの前後に scollTop を測定し、setTimeout を使用してネイティブ スクロールを可能にすることでスクロール オフセットを正しく決定します。

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);
}
于 2013-11-11T22:51:47.620 に答える
1

@ ds111 s と同様の問題がありました。私のウェブサイトはキーボードによって押し上げられましたが、キーボードを閉じても下に移動しませんでした.

最初に @ds111 ソリューションを試しましたが、2 つのinputフィールドがありました。もちろん、最初にキーボードが消えてから、ぼかしが発生します (またはそのようなもの)。inputそのため、フォーカスが一方の入力から他方の入力に直接切り替わったとき、2 つ目はキーボードの下にありました。

さらに、ページ全体がiPadのサイズしかないため、「ジャンプアップ」は私には十分ではありませんでした. というわけで、スクロールをスムーズにしました。

最後に、現在非表示になっているものも含め、すべての入力にイベント リスナーをアタッチする必要があったため、live.

すべて一緒に、次の JavaScript スニペットを次のように説明できます: 次のぼかしイベント リスナーを現在およびすべての将来にアタッチし、input( textarea= live): 猶予期間 (= window.setTimeout(..., 10)) を待ち、スムーズに一番上までスクロールします (= animate({scrollTop: 0}, ...)) ただし、「キーボードがない場合のみ」示されている」 (= 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)
})

猶予期間 (= 10) が短すぎるか、キーボードがまだ表示されていないinputtextarea、フォーカスされていない場合があることに注意してください。もちろん、スクロールを速くしたい場合や遅くしたい場合は、期間を調整できます (= 400)

于 2013-08-31T13:19:41.643 に答える
1

この回避策を見つけるのに本当に苦労しました。これは、入力のフォーカス イベントとブラー イベントを探し、イベントが発生したときにスクロールして固定バーの位置を選択的に変更することです。これは防弾であり、すべてのケース (<>、スクロール、完了ボタンによる移動) をカバーします。注 id="nav" は私の固定フッター div です。これを標準の js または jquery に簡単に移植できます。ここは電動工具を使う人のための道場です ;-)

define([ "dojo/ready", "dojo/query", ], function(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 );
    }

});

}); //定義終了

于 2013-09-26T16:10:26.657 に答える
1

これは「正しく」理解するのが難しい問題です。入力要素のフォーカスでフッターを非表示にし、ぼかしで表示することはできますが、iOS では常に信頼できるとは限りません。ときどき (たとえば、私の iPhone 4S では 10 分の 1 の頻度で) フォーカス イベントが発生しない (または競合状態がある可能性がある) ように見え、フッターが非表示になりません。

多くの試行錯誤の後、私はこの興味深い解決策を思いつきました:

<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>

基本的には、JavaScript を使用してデバイスのウィンドウの高さを決定し、CSS メディア クエリを動的に作成して、ウィンドウの高さが 10 ピクセル縮小したときにフッターを非表示にします。キーボードを開くとブラウザーの表示サイズが変更されるため、iOS ではこれが失敗することはありません。JavaScript ではなく CSS エンジンを使用しているため、はるかに高速でスムーズです。

注: 「visibility:hidden」を使用すると、「display:none」または「position:static」よりもグリッチが少ないことがわかりましたが、マイレージは異なる場合があります。

于 2013-11-25T08:44:05.247 に答える
1

私たちの場合、これはユーザーがスクロールするとすぐに修正されます。blurしたがって、これはanyinputまたはのスクロールをシミュレートするために使用してきた修正textareaです。

$(document).on('blur', 'input, textarea', function () {
    setTimeout(function () {
        window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
    }, 0);
});
于 2014-07-10T07:23:29.900 に答える
1

私の答えは、それはできないということです。

25 の回答が表示されますが、私の場合はどれも機能しません。そのため、Yahoo などのページでは、キーボードをオンにすると固定ヘッダーが非表示になります。また、Bing はページ全体をスクロール不可 (overflow-y: hidden) にします。

上記で説明したケースは異なります。スクロール時に問題が発生したり、フォーカスやぼかしに問題が発生したりする場合があります。フッターまたはヘッダーが固定されているものもあります。各組み合わせを今すぐテストすることはできませんが、あなたのケースではそれができないことに気付くかもしれません.

于 2017-02-09T09:06:04.123 に答える
0

Github でこのソリューションを見つけました。

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

スクロール可能なコンテンツがあることを確認してください。

// 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>

追加のボーナスとして、アドレスバーが折りたたまれます。

于 2013-04-17T07:46:15.300 に答える
0

これは、iOS 8.3 のより背の高い Bootstrap Modals を使用する HTML ページの大きなバグです。上記の提案されたソリューションはどれも機能せず、背の高いモーダルのフォールドの下にあるフィールドにズームインした後、モバイル Safari および/または WkWebView は、固定要素を HTML 本文のスクロールが配置された場所に移動し、実際の場所とずれて配置されたままにします。レイアウト。

このバグを回避するには、次のようなモーダル入力にイベント リスナーを追加します。

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

HTMLボディのスクロールの高さを強制すると、実際のビューがiOS 8 WebViewが固定モーダルdivのコンテンツがあると予想される場所に再調整されるため、これが機能すると推測しています。

于 2015-05-28T20:46:41.933 に答える
0

このスレッドのすべてのアプローチを試しましたが、役に立たなかった場合はさらに悪化しました。最後に、強制的にデバイスにフォーカスを失わせることにしました。

$(<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);
    }
});

それは魔法のように機能し、粘着性のあるログインフォームを修正しました。

注意してください:

  1. 上記の JS コードは私の考えを示すためだけのものです。このスニペットを実行するには、角括弧 (<>) 内の値を状況に応じた適切な値に置き換えてください。
  2. このコードは、jQuery v1.10.2
于 2013-07-19T16:24:24.663 に答える
0

iOS9 - 同じ問題。

TLDR - 問題の原因。解決策については、一番下までスクロールしてください

position:fixediframe に id='subscribe-popup-frame' のフォームがありました

元の質問によると、入力フォーカスでは、iframe は画面の上部ではなくドキュメントの上部に移動します。

ユーザーエージェントが idevice に設定されている safari dev モードでは、同じ問題は発生しませんでした。そのため、iOS 仮想キーボードがポップアップしたときに問題が発生したようです。

コンソールが iframe の位置 (例: ) をログに記録することで、何が起こっているかをある程度把握できました。そこから、仮想キーボードがポップアップしたとき (つまり、入力要素にフォーカスしたとき$('#subscribe-popup-frame', window.parent.document).position()) に iOS が要素の位置を設定しているように見えることがわかりました。{top: -x, left: 0}

したがって、私の解決策は、その厄介な を取り-x、符号を逆にしてから、jQuery を使用してそのtop位置を iframe に戻すことでした。より良い解決策があればぜひ聞きたいのですが、さまざまなアプローチを試した後、それが唯一の解決策でした。

欠点: 500 ミリ秒のタイムアウトを設定する必要がありました (それよりも短い時間でも動作する可能性がありますが、安全を確保したかったためです) x。その結果、経験は非常にぎくしゃくしています。. . しかし、少なくともそれは機能します

解決

        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);
            }    
        }   

次にmobileInputReposition、次のようなものを$('your-input-field).focus(function(){})呼び出すだけです$('your-input-field).blur(function(){})

于 2016-06-16T03:51:57.063 に答える