技术, 前端

修复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:

$(function () {
    if (Modernizr.touch) {
        $(document).on('focus', 'input', function () {
            $(".navbar-fixed-top").addClass('fixfixed');
        });

        $(document).on('blur', 'input', function () {
            $(".navbar-fixed-top").removeClass('fixfixed');
        });
    }
});

使用了Modernizr,仅在触屏上进行处理,对桌面浏览器不做处理,这样对于桌面浏览器上的体验更好。

完美解决问题!

by HADB

2015/4/13 凌晨 于 家中

您已成功订阅 HADB.ME
真棒!下一步,完成结账以便解锁 HADB.ME
欢迎回来!您已登录成功。
登录失败,请重试。
操作成功!您的账户已全面激活,现在您有所有内容的权限了。
错误!Stripe 结账失败。
成功!您的账单信息已更新。
错误!账单信息更新失败。