iOS 5固定定位和虚拟键盘

我有一个移动网站,有一个div固定在屏幕的底部通过位置:固定。 所有在iOS 5中正常工作(我正在testing一个iPod Touch),直到我在一个表单的页面上。 当我点击一个input字段,虚拟键盘出现时,突然我的div的固定位置丢失。 只要键盘可见,div就会滚动页面。 一旦我点击完成closures键盘,div恢复到它在屏幕底部的位置,并服从位置:固定的规则。

有没有人经历过这种行为? 这是预期的吗? 谢谢。

我的应用程序中遇到了这个问题。 以下是我如何解决这个问题:

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

我只是滚动到顶端,并将其放置在那里,所以iOS用户不会注意到任何奇怪的事情。 将其包含在某些用户代理检测中,以便其他用户不会得到此行为。

我有一个略有不同的ipad问题,其中虚拟键盘将视口向上推离屏幕。 然后,用户closures虚拟键盘后,我的视口仍然离屏。 就我而言,我做了如下的事情:

 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认为页面已经resize,但是元素会重新定位自己。 这并不完美,但至less您不必担心切换到“绝对位置”并自己跟踪更改。

下面的代码只是监听用户何时可能正在使用键盘(由于input被聚焦),直到听到模糊,它只是监听任何滚动事件,然后执行resize的技巧。 似乎到目前为止我工作得很好。

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

以防万一有人在研究这个问题时发生这种情况。 我发现这个线程有助于激发我对这个问题的思考。

这是我最近的一个项目的解决scheme。 您只需要将“targetElem”的值更改为表示您的标题的jQueryselect器。

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

我有两个固定的navbars(页眉和页脚,使用twitter引导)。 当键盘出现exception时,它们都performance得怪怪怪怪,键盘出现exception后又出现怪异现象。

有了这个定时/延迟修复它的作品。 我偶尔会发现一个小故障,但它似乎足以向客户展示。

让我知道这是否适合你。 如果不是,我们可能会find别的东西。 谢谢。

我发现这个错误的其他答案都没有为我工作。 我能够通过简单地将页面滚动回34px来解决这个问题,移动Safari浏览器会将其滚动下来。 与jQuery的:

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

这显然会在所有的浏览器中生效,但是它可以防止在iOS中崩溃。

我遇到与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 

希望能帮助别人。

我已经采取了Jory Cunningham答案和改进:

在很多情况下,它不仅仅是一个疯狂的元素,而是几个固定的元素,所以在这种情况下, targetElem应该是一个jQuery对象,它拥有所有你想“修复”的固定元素。 何,这似乎使iOS键盘消失,如果你滚动…

不用提,你应该使用这个AFTER文档的DOM ready事件,或者在closures</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的解决scheme,除了我的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); } 

是的,似乎苹果公司对IOS5没有这么好的想法。 一旦出现虚拟键盘,任何固定的位置元素就相对于页面变得相对。 如果元素恢复到绝对位置,这可能是确定的,因为这不会破坏布局。 不幸的是,这些元素的实际位置远远不能预测。

我在[编辑]的固定标题中遇到了这个确切的问题。 向下滚动页面,然后点击search框和砰…布局破碎。 我甚至试图通过恢复焦点事件的绝对定位来解决这个问题,但是这样我就失去了焦点(键盘保持打开状态,但光标不再在search框中)。

无论如何,我正在努力,所以我会让你知道,如果我sorting

干杯

我已经固定了我的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); 

我有一个类似的问题@ ds111 s。 我的网站被键盘推上去,但键盘closures时没有下移。

首先,我尝试@ ds111解决scheme,但我有两个input字段。 当然,首先键盘消失,然后发生模糊(或类似的东西)。 所以第二个input是在键盘下,当焦点直接从一个input切换到另一个。

此外,“跳”对我来说还不够好,因为整个页面只有ipad的大小。 所以我做了滚动顺利。

最后,我必须将事件监听器附加到所有的input,甚至是那些当前隐藏的input,因此是live

所有在一起,我可以解释以下javascript代码段为:将以下模糊事件侦听器附加到当前和所有未来inputtextarea (= 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 )可能太短,或键盘仍然可以显示,尽pipe没有inputtextarea焦点。 当然,如果你想滚动更快或更慢,你可以调整持续时间(= 400

真的很努力地find这个解决方法,简而言之,它会在input中查找焦点和模糊事件,并在事件发生时滚动以select性地更改固定栏的位置。 这是防弹的,涵盖所有情况(使用<>,滚动,完成button导航)。 注意id =“nav”是我的固定页脚div。 你可以轻松地将其移植到标准的js或jquery。 这是使用电动工具的人的道场;-)

define([“dojo / ready”,“dojo / 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 ); } }); 

}); //结束定义

这是一个难以获得“正确”的难题。 您可以尝试隐藏input元素焦点上的页脚,并显示模糊,但在iOS上这并不总是可靠的。 每隔一段时间(在iPhone 4S上说十次中的一次),焦点事件似乎不能触发(或者可能存在竞争条件),并且页脚不会被隐藏。

经过多次尝试和错误,我想出了这个有趣的解决scheme:

 <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来确定设备的窗口高度,然后dynamic创build一个CSS媒体查询来隐藏页脚,当窗口的高度缩小10个像素。 由于打开键盘会调整浏览器显示的大小,因此在iOS上不会失败。 因为它使用的是CSS引擎而不是JavaScript,所以它更快更顺畅!

注:我发现使用“可视性:隐藏”比“显示器:无”或“位置:静态”更less毛刺,但是你的里程可能会有所不同。

为我工作

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

在我们的情况下,只要用户滚动,就会自动修复。 所以这是我们用来模拟任何inputtextarea blur滚动的修复:

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

在Github上find这个解决scheme。

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> 

地址栏作为额外的奖励折叠起来。

如果有人想尝试这个。 我有一个固定的脚注,其中有一个input字段,为我工作。

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

我有同样的问题。 但是我意识到,固定的位置只是延迟了,并没有被打破(至less对我而言)。 等待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); } }); 

它像一个魅力和固定我粘滞的login表单。

注意:

  1. 上面的JS代码只是为了展示我的想法,要执行这个代码片段,请使用适当的值代替angular度大括号(<>)中的值。
  2. 此代码旨在与jQuery v1.10.2

对于iOS 8.3中任何具有较高Bootstrap Modals的HTML页面,这仍然是一个很大的bug。 以上提出的解决scheme都没有工作,并且在放大高于模式的折叠之下的任何字段之后,移动Safari和/或WkWebView会将固定元素移动到HTML主体的滚动位置,使得它们与他们实际的位置摆放。

为了解决这个问题,可以将一个事件监听器添加到任何模态input中,例如:

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

我猜这是有效的,因为迫使HTML主体的滚动高度重新alignment实际的视图与iOS 8 WebView的固定模态div的内容所在的位置。

如果有人正在寻找一个完全不同的路线(例如,你甚至不打算在你滚动这个“页脚”div,但你只是想让div停留在页面的底部),你可以设置页脚位置为相对的。

这意味着,即使虚拟键盘出现在您的移动浏览器上,页脚也会停留在页面底部,而不是试图对虚拟键盘显示或closures做出反应。

很明显,如果位置固定,页脚在页面上下滚动,但是由于Chrome上的这个奇怪的错误,我们最终转而select了页脚。

滚动的解决scheme似乎没有为我工作。 相反,当用户正在编辑文本时,将正文的位置设置为固定,然后在用户完成时将其恢复为静态。 这使Safari浏览器无法滚动您的内容。 你可以对元素进行焦点/模糊处理(下面显示的是单个元素,但可以是所有input,textareas),或者如果用户正在开始编辑,比如打开模式,你可以做它在那个行动(例如模态开放/closures)。

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

iOS9 – 同样的问题。

TLDR – 问题的根源。 为了解决scheme,请滚动到底部

我有一个position:fixed的formsposition:fixed ID ='subscribe-popup-frame'

根据原始问题,在input焦点上,iframe将会转到文档的顶部,而不是屏幕的顶部。

在用户代理设置为idevice的情况下,safari dev模式中也没有发生同样的问题。 所以这个问题似乎是由iOS虚拟键盘popup时造成的。

我对控制台loggingiframe位置(例如$('#subscribe-popup-frame', window.parent.document).position() )的位置有了一些了解,我可以看到iOS似乎设置了当虚拟键盘popup(即集中在input元素上)时元素的位置为{top: -x, left: 0}

所以我的解决scheme是采取这个麻烦-x ,扭转标志,然后使用jQuery将该top位置添加回iframe。 如果有更好的解决scheme,我很乐意听到它,但尝试了十几种不同的方法后,它是唯一一个为我工作的人。

缺点:我需要设置一个500ms的超时时间(可能会less一些,但我想要安全),以确保在iOS完成对元素位置的恶作剧之后,我捕获了最终的x值。 结果,这个经验非常生涩。 。 。 但至less它工作

  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(){})

我的答案是不能做到的。

我看到25个答案,但没有在我的情况下工作。 这就是为什么雅虎和其他网页在键盘打开时隐藏固定标题。 并且Bing将整个页面变成不可滚动(overflow-y:hidden)。

上面讨论的情况是不同的,有些在滚动时有问题,有些在焦点或模糊。 一些有固定页脚,或标题。 我现在不能testing每个组合,但最终可能会意识到,在你的情况下是无法完成的。