Position:fixedを介して画面の下部に固定されたdivを持つモバイルWebサイトがあります。フォームのあるページを表示するまで、iOS 5(iPod Touchでテスト中)ですべて正常に動作します。入力フィールドをタップして仮想キーボードが表示されると、突然divの固定位置が失われます。キーボードが表示されている限り、divはページとともにスクロールします。 [完了]をクリックしてキーボードを閉じると、divは画面の下部の位置に戻り、position:fixedルールに従います。
他の誰かがこのような行動を経験しましたか?これは予想されますか?ありがとう。
アプリケーションでこの問題が発生しました。これを回避する方法は次のとおりです。
input.on('focus', function(){
header.css({position:'absolute'});
});
input.on('blur', function(){
header.css({position:'fixed'});
});
一番上までスクロールしてそこに配置するだけなので、iOSユーザーは奇妙なことに気づかない。これを一部のユーザーエージェント検出でラップして、他のユーザーがこの動作を取得しないようにします。
仮想キーボードがビューポートを画面外に押し上げるというipadの問題がわずかにありました。その後、ユーザーが仮想キーボードを閉じた後、私のビューポートはまだオフスクリーンでした。私の場合、次のようなことをしました。
var el = document.getElementById('someInputElement');
function blurInput() {
window.scrollTo(0, 0);
}
el.addEventListener('blur', blurInput, false);
これは、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);
}
});
位置が固定された要素は、キーボードが起動しているときに単に位置を更新しません。しかし、Safariをだましてページのサイズが変更されたと思わせることで、要素の位置が変更されることがわかりました。完全ではありませんが、少なくとも「位置:絶対」に切り替えて、自分で変更を追跡することを心配する必要はありません。
次のコードは、ユーザーがキーボードを使用している可能性がある場合(入力がフォーカスされているため)をリッスンし、ぼかしが聞こえるまでスクロールイベントをリッスンし、サイズ変更のトリックを実行します。これまでのところ、私にとってはかなりうまく機能しているようです。
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;
});
この問題の調査中に私がしたように、誰かがこのスレッドに遭遇した場合に備えて。このスレッドは、この問題に関する私の考えを刺激するのに役立ちました。
これは最近のプロジェクトでこれに対する私の解決策でした。 「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操作を停止するため、修正が保留になるのに少し遅れがありますが、トリックは...
この問題は本当に迷惑です。
上記の手法のいくつかを組み合わせて、これを思い付きました。
$(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つの固定navbar(ヘッダーとフッター、Twitterブートストラップを使用)があります。両方とも、キーボードがアップ状態のときは奇妙な動作をし、キーボードがダウンした後は再び奇妙な動作をしました。
この時間指定/遅延修正により、動作します。私はまだ時々不具合を見つけますが、クライアントにそれを示すのに十分なようです。
これがあなたのために働くかどうか私に知らせてください。そうでない場合、他の何かを見つけることができます。ありがとう。
このバグについて私が見つけた他の答えはどれも私にとってはうまくいきませんでした。ページを34pxだけ上にスクロールすることで修正できました。モバイルサファリの量が下にスクロールします。 jqueryを使用:
$('.search-form').on('focusin', function(){
$(window).scrollTop($(window).scrollTop() + 34);
});
これは明らかにすべてのブラウザで有効になりますが、iOSでの破損を防ぎます。
私はJory Cunningham
答えを取り、それを改善しました:
多くの場合、頭がおかしいのは1つの要素だけではなく、いくつかの固定配置要素です。この場合、targetElem
は「修正」したいすべての固定要素を持つjQueryオブジェクトである必要があります。ほら、これはスクロールするとiOSキーボードが消えてしまうようです...
言うまでもなく、これは_ _の後 document 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');
}
})();
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
それが誰かを助けることを願っています。
私は@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);
}
はい、Appleは、IOS5でこれをあまりよく考えていなかったようです。仮想キーボードが表示されるとすぐに、固定位置の要素はページに対して相対的になります。要素が絶対位置に戻っても、レイアウトを壊さないため、おそらく大丈夫でしょう。残念ながら、これらの要素の実際の配置は予測がはるかに困難です。
[編集済み]の固定ヘッダーにこの問題があります。ページを下にスクロールし、検索ボックスをクリックして、レイアウトが壊れています。フォーカスイベントの絶対位置に戻すことで修正しようとしましたが、動作しますが、フォーカスは失われます(キーボードは開いたままですが、カーソルは検索ボックスにありません)。
とにかく作業中なので、並べ替えたらお知らせします
乾杯
私のために働く
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'});
});
}
私の答えは、それができないということです。
25個の回答が表示されますが、私の場合はうまくいきません。キーボードがオンのとき、Yahooや他のページが固定ヘッダーを隠すのはそのためです。また、Bingはページ全体をスクロール不可にします(オーバーフローy:非表示)。
上記のケースは異なり、スクロール時の問題、フォーカスまたはブラーに関する問題があります。フッターまたはヘッダーが固定されているものもあります。私は今、各組み合わせをテストすることはできませんが、あなたの場合はそれを行うことができないことに気付くかもしれません。
@ ds111と同様の問題がありました。私のウェブサイトはキーボードによって押し上げられましたが、キーボードを閉じても下に移動しませんでした。
最初に@ ds111ソリューションを試しましたが、2つのinput
フィールドがありました。もちろん、最初にキーボードが消え、次にぼかしが発生します(またはそのようなもの)。そのため、2番目のinput
は、フォーカスが1つの入力から別の入力に直接切り替わったときにキーボードの下にありました。
さらに、ページ全体のサイズはiPadのサイズしかないため、「ジャンプアップ」だけでは十分ではありませんでした。そこで、スクロールをスムーズにしました。
最後に、現在非表示になっているすべての入力、つまりlive
にイベントリスナーをアタッチする必要がありました。
まとめて、次のJavaScriptスニペットを次のように説明できます。現在および将来のinput
およびtextarea
(= live
)に次のblurイベントリスナーをアタッチします。猶予期間(= 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
)が短すぎるか、input
またはtextarea
がフォーカスされていないにもかかわらずキーボードが表示されたままになる可能性があることに注意してください。もちろん、スクロールを速くしたり遅くしたい場合は、継続時間を調整できます(= 400
)
これは「正しく」行うのが難しい問題です。入力要素のフォーカスでフッターを非表示にしたり、ぼかしで表示したりできますが、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を使用してデバイスのウィンドウの高さを決定し、ウィンドウの高さが10ピクセル縮小したときにフッターを非表示にするCSSメディアクエリを動的に作成します。キーボードを開くとブラウザのディスプレイのサイズが変更されるため、iOSでこれが失敗することはありません。 JavaScriptではなくCSSエンジンを使用しているため、はるかに高速でスムーズです。
注:「display:none」または「position:static」よりも「visibility:hidden」の方がグリッチが少ないことがわかりましたが、走行距離は異なる場合があります。
このようにして、iPadのメインレイアウトのコンテンツの固定位置を修正しました。
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);
私たちの場合、これはユーザーがスクロールするとすぐに修正されます。これが、blur
またはinput
のtextarea
のスクロールをシミュレートするために使用してきた修正です。
$(document).on('blur', 'input, textarea', function () {
setTimeout(function () {
window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
}, 0);
});
入力のフォーカスイベントとブラーイベントを簡単に検索し、イベントが発生したときに固定バーの位置を選択的に変更するためにスクロールするこの回避策を見つけるために、本当に一生懸命働きました。これは防弾であり、すべてのケースをカバーします(<>、スクロール、完了ボタンでナビゲート)。注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 );
}
});
}); //定義を終了
iOS9-同じ問題。
TLDR-問題の原因。解決策については、下にスクロールしてください
Id = 'subscribe-popup-frame'のposition:fixed
iframeにフォームがありました
元の質問によると、入力フォーカスでは、iframeは画面の上部ではなくドキュメントの上部に移動します。
ユーザーエージェントがideviceに設定されているサファリdevモードでは、同じ問題は発生しませんでした。そのため、問題はポップアップしたときにiOS仮想キーボードによって引き起こされているようです。
Iframeの位置を記録するコンソール(たとえば$('#subscribe-popup-frame', window.parent.document).position()
)で何が起こっているのかを可視化し、そこから仮想キーボードがポップアップしたときにiOSが要素の位置を{top: -x, left: 0}
に設定しているように見える(つまり、入力要素に焦点を当てています)。
したがって、私の解決策は、その厄介な-x
を取得し、符号を逆にしてから、jQueryを使用してそのtop
位置をiframeに追加することでした。より良い解決策があれば、それを聞きたいと思いますが、数十の異なるアプローチを試した後、それが私のために働いた唯一のものでした。
欠点:タイムアウトを500ミリ秒に設定する必要がありました(おそらく機能しなかったかもしれませんが、安全にしたかったため)。iOSが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);
}
}
次に、$('your-input-field).focus(function(){})
や$('your-input-field).blur(function(){})
などのmobileInputReposition
を呼び出します。
これは、iOS 8.3で背の高いBootstrap Modalsを持つHTMLページの大きなバグです。上記の提案された解決策はどれも機能せず、背の高いモーダルの折り目の下のフィールドにズームインした後、Mobile Safariおよび/またはWkWebViewは固定要素をHTML本文のスクロールが配置されている場所に移動し、それらがどこにあるのか不揃いのままにします- 実際レイアウトされている場所。
バグを回避するには、次のようなモーダル入力のいずれかにイベントリスナーを追加します。
$(select.modal).blur(function(){
$('body').scrollTop(0);
});
これは、HTMLボディのスクロール高さを強制すると、iOS 8 WebViewが固定モーダルdivのコンテンツを予期する場所に実際のビューを再配置するため、機能すると推測しています。
誰かが完全に異なるルートを探していた場合(スクロールするときにこの「フッター」divを固定することすら見ていませんが、divをページの下部に留めたいだけの場合)、フッターの位置を次のように設定できます。相対的。
つまり、モバイルブラウザーに仮想キーボードが表示されても、フッターはページの下部に固定されたままになり、仮想キーボードの表示や終了に反応しようとしません。
位置が固定され、上下にスクロールするときにフッターがページに続くと、Safariでは明らかに良くなりますが、Chromeのこの奇妙なバグのために、フッターを相対的にするだけに切り替えました。
誰かがこれを試してみたいと思った場合に備えて。入力フィールドを含む固定フッターで次の機能を使用できます。
<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>
このソリューションは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>
追加のボーナスとして、アドレスバーが折りたたまれます。
スクロールの解決策はどれも私にとってはうまくいかないようでした。代わりに、ユーザーがテキストを編集している間に本文の位置を固定に設定し、ユーザーが完了したらテキストを静的に復元するのが効果的です。これにより、サファリがコンテンツをスクロールするのを防ぎます。これは、要素のフォーカス/ぼかし(単一の要素については下に表示されますが、すべての入力、テキストエリアに対して可能です)、またはユーザーがモーダルを開くなどの編集を開始する場合に行うことができますそのアクション(モーダルオープン/クローズなど)でそれ。
$("#myInput").on("focus", function () {
$("body").css("position", "fixed");
});
$("#myInput").on("blur", function () {
$("body").css("position", "static");
});
同じ問題があります。しかし、私は(少なくとも私にとっては)固定位置が遅れているだけで壊れていないことに気付きました。 5〜10秒待って、divが画面の下部に戻るかどうかを確認します。エラーではなく、キーボードが開いているときの応答が遅れていると思います。
私はこのスレッドからすべてのアプローチを試みましたが、もし助けなければ、さらに悪化しました。最終的に、強制的にデバイスのフォーカスを緩めることにしました。
$(<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);
}
});
そして、それは魅力のように働き、私の粘着性のあるログインフォームを修正しました。
注:
jQuery v1.10.2
で動作するように設計されています