我有一个移动网站,有一个div固定在屏幕底部的位置:固定。一切都在iOS 5中正常工作(我在iPod Touch上测试),直到我在一个带有表单的页面上。当我点击输入字段并出现虚拟键盘时,我的div的固定位置突然丢失。只要键盘可见,div就会随页面滚动。单击完成以关闭键盘后,div将恢复到屏幕底部的位置并遵循位置:固定规则。
有没有其他人经历过这种行为?这是预期的吗?感谢。
答案 0 :(得分:48)
我的申请中遇到了这个问题。以下是我如何解决这个问题:
input.on('focus', function(){
header.css({position:'absolute'});
});
input.on('blur', function(){
header.css({position:'fixed'});
});
我只是滚动到顶部并将其定位在那里,因此iOS用户不会注意到任何奇怪的事情。在一些用户代理检测中包含此内容,以便其他用户不会出现此行为。
答案 1 :(得分:15)
我的ipad问题略有不同,虚拟键盘将我的视口推到了屏幕外。然后在用户关闭虚拟键盘后,我的视口仍在屏幕外。就我而言,我做了类似以下的事情:
var el = document.getElementById('someInputElement');
function blurInput() {
window.scrollTo(0, 0);
}
el.addEventListener('blur', blurInput, false);
答案 2 :(得分: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);
}
});
答案 3 :(得分:12)
当键盘启动时,位置固定元素不会更新它们的位置。我发现通过欺骗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;
});
答案 4 :(得分: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操作,但它可以解决问题......
答案 5 :(得分:4)
我发现这个错误的其他答案都没有对我有用。我能够通过将页面向上滚动34px来修复它,移动数据库的数量会向下滚动。用jquery:
$('.search-form').on('focusin', function(){
$(window).scrollTop($(window).scrollTop() + 34);
});
这显然会在所有浏览器中生效,但它可以防止它在iOS中崩溃。
答案 6 :(得分: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);
});
我有两个固定的导航栏(页眉和页脚,使用twitter bootstrap)。 当键盘启动时,两者都表现得很奇怪,而在键盘关闭后,两者都很奇怪。
通过此定时/延迟修复,它可以正常工作。我偶尔会发现一个小故障,但它似乎足以向客户展示它。
如果这对您有用,请告诉我。如果没有,我们可能会找到别的东西。感谢。
答案 7 :(得分:3)
我遇到了与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
希望能有所帮助。
答案 8 :(得分:3)
我已经 Jory Cunningham
回答并对其进行了改进:
在许多情况下,它不仅仅是一个疯狂的元素,而是几个固定的元素,所以在这种情况下,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');
}
})();
答案 9 :(得分: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);
}
答案 10 :(得分:1)
我的回答是它无法完成。
我看到了25个答案但在我的案例中没有任何效果。这就是为什么雅虎和其他页面在键盘打开时隐藏固定标题的原因。 Bing使整个页面不可滚动(overflow-y:hidden)。
上面讨论的案例有所不同,有些在滚动时有问题,有些在焦点或模糊时有问题。有些人有固定的页脚或标题。我现在无法测试每个组合,但您可能最终意识到在您的情况下无法完成。
答案 11 :(得分:1)
在我们的案例中,一旦用户滚动,这将自行修复。因此,这是我们用来模拟任何blur
或input
上的textarea
滚动的修补程序:
$(document).on('blur', 'input, textarea', function () {
setTimeout(function () {
window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
}, 0);
});
答案 12 :(得分:1)
为我工作
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'});
});
}
答案 13 :(得分:1)
这是一个“正确”的难题。您可以尝试在输入元素焦点上隐藏页脚,并在模糊时显示,但在iOS上并不总是可靠。每隔一段时间(十次,例如,在我的iPhone 4S上),焦点事件似乎无法触发(或者可能存在竞争条件),并且页脚不会被隐藏。
经过多次反复试验,我想出了这个有趣的解决方案:
<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上永远不会失败。因为它使用的是CSS引擎而不是JavaScript,所以它更快更顺畅!
注意:我发现使用'visibility:hidden'比'display:none'或'position:static'更少,但你的里程可能会有所不同。
答案 14 :(得分:1)
确实很难找到这种解决方法,简而言之就是在输入上查找焦点和模糊事件,并在事件发生时滚动选择性地更改固定条的位置。这是防弹的,涵盖所有情况(使用&lt;&gt;,滚动,完成按钮导航)。注意id =“nav”是我固定的页脚div。您可以轻松地将其移植到标准js或jquery。这是使用电动工具的人的道场; - )
定义([ “道场/就绪”, “道场/查询”, ],函数(准备好,查询){
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 );
}
});
}); //结束定义
答案 15 :(得分:1)
我和@ ds111有类似的问题。我的网站被键盘向上推,但在键盘关闭时没有向下移动。
首先我尝试了@ ds111解决方案,但我有两个input
字段。当然,首先键盘消失,然后发生模糊(或类似的事情)。所以当焦点直接从一个输入切换到另一个输入时,第二个input
在键盘下面。
此外,“跳起来”对我来说不够好,因为整个页面只有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
)可能太短,或者虽然没有input
或textarea
聚焦,但键盘仍然可能会显示。当然,如果您希望滚动更快或更慢,您可以调整持续时间(= 400
)
答案 16 :(得分:1)
我已经通过这种方式修复了我的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);
答案 17 :(得分: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);
}
});
它就像魅力一样,修复了我的粘性登录表单。
请注意:
jQuery v1.10.2
答案 18 :(得分:0)
我有同样的问题。但我意识到固定位置只是延迟而不是破坏(至少对我而言)。等待5-10秒,看看div是否调整回屏幕底部。我相信这不是错误,而是键盘打开时的延迟响应。
答案 19 :(得分:0)
如果有人想试试这个。我在固定的页脚上为我工作,其中包含一个输入字段。
<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>
答案 20 :(得分:0)
对于iOS 8.3中具有较高Bootstrap Modals的任何HTML页面,这仍然是一个大错误。以上提出的解决方案都没有工作,并且在放大高模式折叠下方的任何字段后,Mobile Safari和/或WkWebView会将固定元素移动到HTML主体滚动所在的位置,从而使它们不对齐他们实际上所在的地方。
要解决此问题,请为您的任何模态输入添加事件侦听器,例如:
$(select.modal).blur(function(){
$('body').scrollTop(0);
});
我猜这是有效的,因为强制HTML正文的滚动高度将实际视图与iOS 8 WebView期望固定模态div内容的位置重新对齐。
答案 21 :(得分:0)
如果有人在寻找一条完全不同的路线(就像你在滚动时甚至不想固定这个“页脚”div那么你只想让div留在页面的底部),你可以设置页脚位置为相对位置。
这意味着即使虚拟键盘出现在您的移动浏览器上,您的页脚也会保持固定在页面底部,而不是尝试对虚拟键盘显示或关闭做出反应。
显然,如果位置固定并且在向上或向下滚动页脚跟随页面时它看起来更好看,但由于Chrome上的这个奇怪的错误,我们最终切换到只是使页脚相对。
答案 22 :(得分:0)
所有滚动解决方案似乎都不适合我。相反,有效的方法是在用户编辑文本时将主体的位置设置为固定,然后在用户完成时将其恢复为静态。这使得safari不会滚动您的内容。您可以在元素的焦点/模糊上执行此操作(下面显示单个元素,但可以用于所有输入,textareas),或者如果用户正在执行某些操作以开始编辑,例如打开模态,则可以执行此操作它就是那个动作(例如模态打开/关闭)。
$("#myInput").on("focus", function () {
$("body").css("position", "fixed");
});
$("#myInput").on("blur", function () {
$("body").css("position", "static");
});
答案 23 :(得分:0)
iOS9 - 同样的问题。
TLDR - 问题的根源。对于解决方案,请滚动到底部
我在position:fixed
iframe中有一个表单,其中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毫秒(可能更少会工作,但我想保证安全),以确保我在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);
}
}
然后只需拨打mobileInputReposition
和$('your-input-field).focus(function(){})
$('your-input-field).blur(function(){})
即可
答案 24 :(得分: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>
地址栏折叠起来作为额外奖励。