修复 position:fixed 在 ios 虚拟键盘弹出时错位的 bug
问题描述:在使用 bootstrap 的 navbar-fixed-top 时,发现在 iPhone 上的微信里面,当点击 input 弹出输入法之后,顶部 fixed 的 navbar 消失,在输入法没有关闭的情况下,向上滚动,会发现 navbar 在半空中。
Google 了一下,发现这个问题在 iOS 中很常见,Bootstrap 也对此进行了说明(戳这里)。
Virtual keyboards
Also, note that if you're using a fixed navbar or using inputs within a modal, iOS has a rendering bug that doesn't update the position of fixed elements when the virtual keyboard is triggered. A few workarounds for this include transforming your elements to position: absolute or invoking a timer on focus to try to correct the positioning manually. This is not handled by Bootstrap, so it is up to you to decide which solution is best for your application.
不过我在最近刚更新的 iOS8.3 的 Safari 中,没有发现这个问题。在 8.3 的 Safari 中,点击 input 弹出输入法之后,fixed 元素会失效,navbar 回到最顶端,没有浮在半空中。猜测是在弹出虚拟键盘之后为了节省页面空间,而对 fixed 的元素进行了处理,但是在微信中的浏览器上处理出了点问题。
目前发现最好的解决方案是在点击 input 之后,直接把 fixed 的元素变成 absolute 的,不需要浏览器自己去做处理。
有人说在滚动时用 timer 实时调整元素位置,我觉得这个很低端。浏览器去处理 fixed 元素自然有它的道理,确实可以节省屏幕空间。我们其实也没有必要在这个情况下强制显示 navbar,这时用户的重点在于输入。当我们 input 失去焦点之后,输入法关闭,这时我们再显示出 navbar。
下面直接上代码:
添加这样一段 css:
.fixfixed.navbar-fixed-top {
position: absolute;
}
添加这样一段 js:
$(() => {
if (Modernizr.touch) {
$(document).on('focus', 'input', () => {
$('.navbar-fixed-top').addClass('fixfixed')
})
$(document).on('blur', 'input', () => {
$('.navbar-fixed-top').removeClass('fixfixed')
})
}
})
使用了 Modernizr,仅在触屏上进行处理,对桌面浏览器不做处理,这样对于桌面浏览器上的体验更好。
完美解决问题!