我有一个移动网站,该网站的div通过position:fixed固定在屏幕底部。在iOS 5(我正在iPod Touch上进行测试)中,所有方法都可以正常工作,直到出现带有表单的页面为止。当我点击输入字段并出现虚拟键盘时,突然我的div的固定位置丢失了。现在,只要可见键盘,div就会随页面滚动。单击“完成”以关闭键盘后,div将恢复到其在屏幕底部的位置,并遵守position:fixed规则。
有没有其他人经历过这种行为?这是预期的吗?谢谢。
我有一个移动网站,该网站的div通过position:fixed固定在屏幕底部。在iOS 5(我正在iPod Touch上进行测试)中,所有方法都可以正常工作,直到出现带有表单的页面为止。当我点击输入字段并出现虚拟键盘时,突然我的div的固定位置丢失了。现在,只要可见键盘,div就会随页面滚动。单击“完成”以关闭键盘后,div将恢复到其在屏幕底部的位置,并遵守position:fixed规则。
有没有其他人经历过这种行为?这是预期的吗?谢谢。
Answers:
我的应用程序中有这个问题。这是我的解决方法:
input.on('focus', function(){
header.css({position:'absolute'});
});
input.on('blur', function(){
header.css({position:'fixed'});
});
我只是滚动到顶部并将其放置在此处,因此iOS用户不会注意到发生了什么奇怪的事情。将其包装在某些用户代理检测中,以便其他用户不会出现此行为。
document.body.scrollTop = 0
如果您不使用jQuery并定位到最新的浏览器,则很简单。
$(window).scrollTop(0);
会导致焦点输入移出屏幕,例如页面下方的输入,或者iPhone是纵向的。更好的解决方案是聚焦设置header.css({position:'absolute',top:window.pageYOffset+'px'});
和模糊设置header.css({position:'fixed',top:0});
。
我在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操作,因此修复工作会稍有延迟,但这确实可以解决问题。
init
为常规函数(不是自调用;触发得太早了)。然后iOSKeyboardFix.init();
在if
语句结束之前调用。
这个问题真烦人。
我结合了上述一些技巧,并提出了以下建议:
$(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的页眉和页脚)。两者在键盘启动时都表现得很奇怪,而在键盘按下后又表现得很奇怪。
使用此定时/延迟修复程序可以正常工作。我仍然偶尔会发现一个小故障,但似乎足以将其显示给客户。
让我知道这是否适合您。如果没有,我们可能会发现其他东西。谢谢。
我在iOS7上遇到了同样的问题。底部固定元素会使我的视线混乱,无法正确聚焦。
当我将此meta标签添加到我的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
希望能对某人有所帮助。
我已经Jory Cunningham
回答并改进了它:
在许多情况下,不仅一个元素发疯了,而且几个固定位置的元素也变得疯狂,因此在这种情况下,targetElem
应该是一个jQuery对象,其中包含您要“修复”的所有固定元素。,这似乎会使iOS键盘在您滚动时消失。
不用说,您应该在AFTER 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');
}
})();
我有一个类似于@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);
}
我已经通过以下方式固定了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);
setInterval
真的吗 最好只留下错误而不是这样做
我有一个与@ 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
)
找到这种变通办法的过程确实很努力,简而言之就是寻找输入上的焦点和模糊事件,并在事件发生时滚动以选择性地更改固定条的位置。这是防弹的,涵盖了所有情况(使用<>导航,滚动,完成按钮)。注意id =“ nav”是我的固定页脚div。您可以轻松地将此移植到标准js或jquery。对于那些使用电动工具的人来说,这是道场;-)
define([[“ dojo / ready”,“ dojo / query”,],函数(ready,查询){
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 );
}
});
}); //结束定义
overflow:hidden
规则,那么您将完全看不到您的输入,因为它现在位于框外。
这是“正确”的难题。您可以尝试在输入元素焦点上隐藏页脚,并在模糊下显示,但这在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”的毛刺要少,但是您的里程可能会有所不同。
我的回答是无法完成。
我看到25个答案,但在我的情况下却无用。这就是为什么打开键盘时Yahoo和其他页面会隐藏固定标题的原因。并且Bing将整个页面设为不可滚动(overflow-y:隐藏)。
上面讨论的情况是不同的,有些在滚动时有问题,有些在聚焦或模糊上。有些具有固定的页脚或页眉。我现在无法测试每种组合,但是您可能最终意识到无法根据您的情况进行。
在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>
地址栏折叠起来是一个额外的好处。
万一有人想尝试这个。在固定的页脚中有一个输入字段的情况下,我得到了以下工作。
<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>
我尝试了该线程中的所有方法,但如果它们没有帮助,它们甚至会更糟。最后,我决定让装置失去重点:
$(<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
对于iOS 8.3中具有更高Bootstrap Modals的任何HTML页面而言,这仍然是一个很大的错误。上面提出的所有解决方案都无法正常工作,并且在放大高模态折叠下方的任何字段后,Mobile Safari和/或WkWebView都无法将固定元素移动到HTML正文滚动条所在的位置,从而使它们与实际位置未对齐布置。
要解决该错误,请将事件侦听器添加到您的任何模式输入中,例如:
$(select.modal).blur(function(){
$('body').scrollTop(0);
});
我猜这是可行的,因为强制HTML正文的滚动高度将实际视图与iOS 8 WebView期望固定模式div的内容重新对齐。
滚动解决方案似乎都不适合我。相反,有效的方法是在用户编辑文本时将主体的位置设置为固定,然后在用户完成操作后将其恢复为静态。这样可以避免野生动物园在您上滚动内容。您可以对元素进行聚焦/模糊处理(如下所示,用于单个元素,但可以用于所有输入,文本区域),或者如果用户正在做一些事情来开始编辑,例如打开模式,则可以它在该动作上(例如模式打开/关闭)。
$("#myInput").on("focus", function () {
$("body").css("position", "fixed");
});
$("#myInput").on("blur", function () {
$("body").css("position", "static");
});
iOS9-同样的问题。
TLDR-问题的根源。要解决问题,请滚动到底部
我在position:fixed
iframe中有一个ID ='subscribe-popup-frame' 的表单
按照最初的问题,在输入焦点上,iframe会到达文档的顶部,而不是屏幕的顶部。
在将用户代理设置为idevice的Safari开发模式下,没有发生相同的问题。因此看来问题出在iOS虚拟键盘弹出时。
通过控制台记录iframe的位置(例如$('#subscribe-popup-frame', window.parent.document).position()
),我对发生的事情有了一些了解,从那里我可以看到iOS似乎将元素的位置设置{top: -x, left: 0}
为虚拟键盘弹出时(即,专注于输入元素)。
因此,我的解决方案是使该讨厌的事情发生-x
,反转符号,然后使用jQuery将该top
位置添加回iframe。如果有更好的解决方案,我很想听听,但是尝试了十二种不同的方法后,它是唯一对我有用的方法。
缺点:我需要将超时时间设置为500毫秒(也许可以减少工作时间,但是我想保持安全),以确保x
在iOS对元素的位置作了恶作剧后,我捕获了最终值。结果,体验非常生涩。。。但至少它有效
解
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(){})