Ios 在Mobile Safari中打开虚拟键盘时,如何阻止固定导航像这样移动?
我知道MobileSafari在固定元素上有很多bug,但在我将一个非常需要的文本输入添加到底部的固定导航之前,我已经设法让我的布局正常工作了。现在,当用户关注文本输入元素和虚拟键盘出现时,我的导航,否则总是固定在页面底部,跳转到页面中间的一个非常奇怪的位置。 我想在这篇文章中添加一些代码,但我不确定从哪里开始。该导航固定在底部,位于左侧和底部0,宽度为100%。从那里,我不知道发生了什么,我只能假设这是一个移动狩猎错误 只有当文本输入元素被关注并且虚拟键盘处于打开状态时,它似乎也失去了固定的位置并变得相对。这是建议的解决方案之一。看来值得一试 简而言之:当任何输入为Ios 在Mobile Safari中打开虚拟键盘时,如何阻止固定导航像这样移动?,ios,css,mobile,position,mobile-safari,Ios,Css,Mobile,Position,Mobile Safari,我知道MobileSafari在固定元素上有很多bug,但在我将一个非常需要的文本输入添加到底部的固定导航之前,我已经设法让我的布局正常工作了。现在,当用户关注文本输入元素和虚拟键盘出现时,我的导航,否则总是固定在页面底部,跳转到页面中间的一个非常奇怪的位置。 我想在这篇文章中添加一些代码,但我不确定从哪里开始。该导航固定在底部,位于左侧和底部0,宽度为100%。从那里,我不知道发生了什么,我只能假设这是一个移动狩猎错误 只有当文本输入元素被关注并且虚拟键盘处于打开状态时,它似乎也失去了固定的
focus
ed时,将fixed
元素设置为position:absolute
,当该元素为blur
红色时,将其重置
.header {
position: fixed;
}
.footer {
position: fixed;
}
.fixfixed .header,
.fixfixed .footer {
position: absolute;
}
及
我真的很喜欢上面的解决方案。我将其打包成一个小jQuery插件,以便:
- 设置获取类的父级
- 设置适用于哪些元素(不要忘记“textarea”和“select”)
- 设置父类的名称
- 让它被锁起来
- 允许多次使用
$.fn.mobileFix = function (options) {
var $parent = $(this),
$fixedElements = $(options.fixedElements);
$(document)
.on('focus', options.inputElements, function(e) {
$parent.addClass(options.addClass);
})
.on('blur', options.inputElements, function(e) {
$parent.removeClass(options.addClass);
// Fix for some scenarios where you need to start scrolling
setTimeout(function() {
$(document).scrollTop($(document).scrollTop())
}, 1);
});
return this; // Allowing chaining
};
// Only on touch devices
if (Modernizr.touch) {
$("body").mobileFix({ // Pass parent to apply to
inputElements: "input,textarea,select", // Pass activation child elements
addClass: "fixfixed" // Pass class name
});
}
添加如下javascript:
$(function() {
var $body;
if ('ontouchstart' in window) {
$body = $("body");
document.addEventListener('focusin', function() {
return $body.addClass("fixfixed");
});
return document.addEventListener('focusout', function() {
$body.removeClass("fixfixed");
return setTimeout(function() {
return $(window).scrollLeft(0);
}, 20);
});
}
});
.fixfixed header{
position: absolute;
}
$window.document.body.addEventListener('focusin', function(event) {
var element = event.target;
var tagName = element.tagName.toLowerCase();
if(!$rootScope.inputOverlay && (tagName === 'input' || tagName === 'textarea' || tagName === 'select')) {
$rootScope.$apply(function() {
$rootScope.inputOverlay = true;
});
}
});
$window.document.body.addEventListener('focusout', function() {
if($rootScope.inputOverlay) {
$rootScope.$apply(function() {
$rootScope.inputOverlay = false;
});
}
});
并添加如下类:
$(function() {
var $body;
if ('ontouchstart' in window) {
$body = $("body");
document.addEventListener('focusin', function() {
return $body.addClass("fixfixed");
});
return document.addEventListener('focusout', function() {
$body.removeClass("fixfixed");
return setTimeout(function() {
return $(window).scrollLeft(0);
}, 20);
});
}
});
.fixfixed header{
position: absolute;
}
$window.document.body.addEventListener('focusin', function(event) {
var element = event.target;
var tagName = element.tagName.toLowerCase();
if(!$rootScope.inputOverlay && (tagName === 'input' || tagName === 'textarea' || tagName === 'select')) {
$rootScope.$apply(function() {
$rootScope.inputOverlay = true;
});
}
});
$window.document.body.addEventListener('focusout', function() {
if($rootScope.inputOverlay) {
$rootScope.$apply(function() {
$rootScope.inputOverlay = false;
});
}
});
你可以参考这篇文章:我对丹·萨金提出的解决方案没有任何运气。也许自从他写了那篇博文后,这个bug已经改变了,但是在iOS 7.1上,当输入模糊后位置变回固定位置时,这个bug总是会出现,即使你延迟到软件键盘完全隐藏为止。我找到的解决方案是等待一个
touchstart
事件,而不是blur
事件,因为当页面滚动时,固定元素总是会捕捉回正确的位置
if (Modernizr.touch) {
var $el, focused;
$el = $('body');
focused = false;
$(document).on('focus', 'input, textarea, select', function() {
focused = true;
$el.addClass('u-fixedFix');
}).on('touchstart', 'input, textarea, select', function() {
// always execute this function after the `focus` handler:
setTimeout(function() {
if (focused) {
return $el.removeClass('u-fixedFix');
}
}, 1);
});
}
HTH顶部的解决方案是解决问题的一些方法,但我认为添加额外的css类或使用Modernize会使事情变得复杂。
如果您想要更简单的解决方案,这是一个非现代化的非额外的css但纯粹的jquery解决方案,适用于我在所有项目中使用此修复程序的所有设备和浏览器
if ('ontouchstart' in window) {
$(document).on('focus', 'textarea,input,select', function() {
$('.navbar.navbar-fixed-top').css('position', 'absolute');
}).on('blur', 'textarea,input,select', function() {
$('.navbar.navbar-fixed-top').css('position', '');
});
}
我使用以下jQuery脚本:
var focus = 0;
var yourInput = $(".yourInputClass");
yourInput.focusin(function(){
if(!focus) {
yourInput.blur();
$("html, body").scrollTop($(document).height());
focus = 1;
}
if(focus) {
yourInput.focus();
focus = 0;
}
});
非常适合我。我也遇到过类似的问题,但我找到了一个解决办法,在输入焦点的body元素中添加以下css类,然后在unfocus中再次删除它:
.u-oh {
overflow: hidden;
height: 100%;
width: 100%;
position: fixed;
}
focusin
和focusout
事件似乎比focus
和blur
事件更适合解决此问题,因为前者一直冒泡到根元素。你就这么看吧
就我个人而言,我使用AngularJS,因此我实现了如下:
$(function() {
var $body;
if ('ontouchstart' in window) {
$body = $("body");
document.addEventListener('focusin', function() {
return $body.addClass("fixfixed");
});
return document.addEventListener('focusout', function() {
$body.removeClass("fixfixed");
return setTimeout(function() {
return $(window).scrollLeft(0);
}, 20);
});
}
});
.fixfixed header{
position: absolute;
}
$window.document.body.addEventListener('focusin', function(event) {
var element = event.target;
var tagName = element.tagName.toLowerCase();
if(!$rootScope.inputOverlay && (tagName === 'input' || tagName === 'textarea' || tagName === 'select')) {
$rootScope.$apply(function() {
$rootScope.inputOverlay = true;
});
}
});
$window.document.body.addEventListener('focusout', function() {
if($rootScope.inputOverlay) {
$rootScope.$apply(function() {
$rootScope.inputOverlay = false;
});
}
});
注意:如果这是mobile Safari,我会有条件地运行此脚本
我在导航栏上放置了一个ng class
属性:
<div class="navbar navbar-default navbar-fixed-top" ng-class="{'navbar-absolute': inputOverlay}">
您可以阅读更多关于
focusin
和focusout
测试此项的信息。它起作用了。我只是测试一下
$(document).on('focus','input', function() {
setTimeout(function() {
$('#footer1').css('position', 'absolute');
$('#header1').css('position', 'absolute');
}, 0);
});
$(document).on('blur','input', function() {
setTimeout(function() {
$('#footer1').css('position', 'fixed');
$('#header1').css('position', 'fixed');
}, 800);
});
根据sylowgreen所做的,关键是在输入
输入时修复主体
。因此:
$("#myInput").on("focus", function () {
$("body").css("position", "fixed");
});
$("#myInput").on("blur", function () {
$("body").css("position", "static");
});
这些解决方案都不适合我,因为我的DOM很复杂,而且我有动态无限滚动页面,所以我必须创建自己的
Background:我使用的是一个固定的标题和一个元素,当用户向下滚动那么远的时候,它会在标题下方粘贴。此元素有一个搜索输入字段。此外,我在向前和向后滚动期间添加了动态页面
问题:在iOS中,只要用户单击固定元素中的输入,浏览器就会一直滚动到页面顶部。这不仅导致了不希望出现的行为,还触发了页面顶部的动态页面添加
预期解决方案:当用户单击粘性元素中的输入时,在iOS中没有滚动(根本没有)
解决方案:
/*Returns a function, that, as long as it continues to be invoked, will not
be triggered. The function will be called after it stops being called for
N milliseconds. If `immediate` is passed, trigger the function on the
leading edge, instead of the trailing.*/
function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this, args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
function is_iOS() {
var iDevices = [
'iPad Simulator',
'iPhone Simulator',
'iPod Simulator',
'iPad',
'iPhone',
'iPod'
];
while (iDevices.length) {
if (navigator.platform === iDevices.pop()) { return true; }
}
return false;
}
$(document).on("scrollstop", debounce(function () {
//console.log("Stopped scrolling!");
if (is_iOS()) {
var yScrollPos = $(document).scrollTop();
if (yScrollPos > 200) { //200 here to offset my fixed header (50px) and top banner (150px)
$('#searchBarDiv').css('position', 'absolute');
$('#searchBarDiv').css('top', yScrollPos + 50 + 'px'); //50 for fixed header
}
else {
$('#searchBarDiv').css('position', 'inherit');
}
}
},250,true));
$(document).on("scrollstart", debounce(function () {
//console.log("Started scrolling!");
if (is_iOS()) {
var yScrollPos = $(document).scrollTop();
if (yScrollPos > 200) { //200 here to offset my fixed header (50px) and top banner (150px)
$('#searchBarDiv').css('position', 'fixed');
$('#searchBarDiv').css('width', '100%');
$('#searchBarDiv').css('top', '50px'); //50 for fixed header
}
}
},250,true));
要求:启动滚动和停止滚动功能需要JQuery mobile
包括去盎司,以消除粘性元素产生的任何滞后
在iOS10中测试。@我刚刚测试过,运气不好。这与移动safari或IOS有关。无论出于何种原因,它在键盘退出时删除固定位置,然后在键盘关闭后,所有内容都返回到其正常位置和属性。这也是为什么它会像那样向上移动固定元素的原因。添加任何样式,例如边距顶部
,顶部
,底部
,到:active
或:focus
伪元素会起作用吗?@albertxing添加215px的负边距底部,这是它被推高的高度,这是我最后一次尝试,但又一次没有运气。好吧,我想这可能是一只狩猎虫。除了等待苹果修复它,我想不出别的办法了。编辑:您是否尝试过底部:-215px
?几个SO问题可能重复。详情请看。啊,这是一个简单而聪明的把戏。谢谢分享,为我工作。丹·萨金的网站并没有解决IOS设备上Chrome浏览器的问题。但是它对Safari.bfred非常有效。请看这个链接,我也尝试在聚焦文本字段时修复标题,但我们没有解决这个问题u-fixedFix类包含什么css?到目前为止,这在我的iPad(iOS 7.1.2-11D257)上不起作用。与wxy112233在回答中使用的类相同的规则,即position:absolute