iOS iPad键盘打开时固定位置会破坏

67

当我点击“搜索表单”文本框时,固定在页面顶部的标题位置会发生断裂。因为它被固定在页面上方,当虚拟键盘弹出时,标题位置会从页面顶部分离并开始浮动到页面中间。

正常情况:

输入图像描述

出现问题:

输入图像描述


我不知道你在这里尝试问什么。这是某种编程问题还是你在询问如何使用移动Safari?也许一张屏幕截图会有所帮助。 - rmaddy
1
这是你的网站吗?作为开发者,你是在问如何修复该网站以便在iPad上正常运行吗?还是你只是该网站的用户,试图弄清楚发生了什么? - rmaddy
1
我是一名开发者,正在寻求关于如何修复这个iOS问题的建议(我认为是这个问题导致的)。 - coldblooded01
请在https://dev59.com/qmsz5IYBdhLWcg3wVGPJ上查看答案。 - Kevin C.
可能是几个SO问题的重复。请参见https://gist.github.com/avesus/957889b4941239490c6c441adbe32398#gistcomment-2193547获取详细信息。 - Brian Cannard
显示剩余2条评论
7个回答

18

我非常喜欢这个解决方案(http://dansajin.com/2012/12/07/fix-position-fixed/)。我将其打包成一个小的jQuery插件,以便我可以:

  • 设置哪个父元素获取该类
  • 设置适用于哪些元素(不要忘记"textarea"和"select")。
  • 设置父类名称是什么
  • 允许链接使用
  • 允许多次使用

代码示例:

$.fn.mobileFix = function (options) {
    var $parent = $(this),

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

编辑:移除不必要的元素


3
好修复,已点赞。不幸的是,这也会使滚动深度跳到顶部,所以一个长的带有页眉输入框(如OP的问题所示)的滚动页面将是糟糕的体验,因为您将失去滚动深度。 - typeoneerror
3
支持@typeoneerror的注意事项:这个方法能解决问题,但是如果没有跟踪位置偏移并找到防止滚动的方法,在长滚动项目上使用固定导航栏时会出现问题。(这是一个不错的解决方案,只是对于那些常见用例有问题。) - Chris Krycho
1
你的代码看起来有 bug。首先,为什么要获取 options.fixedElements 的引用,却在之后没有使用它呢?同样的逻辑,插件中的父元素必须是 $fixedElements,因为从你的示例中可以看出,父元素可能是你想要应用“fixedfix”类的元素,而在你的情况下,该类被应用于 body 上,而所需的元素可能是 header、footer 或其他任何元素。 - Lucaci Andrei
@FlorianB 是的,我的只是一个解决方案,看起来现在的网站使用了jQuery,希望没问题。 - martinedwards
感谢@LucaciAndrei,我删除了fixedElements变量。父元素可以是任何你想要的元素,我选择了body,所以其余部分可以在CSS中完成(请参见我发布的原始文章)。 - martinedwards
这里有一个针对React用户的要点,基于同样的解决方案:https://gist.github.com/pandaiolo/7736141374c900cf0d4e044d181f515e(放弃了IE8兼容性...) - Pandaiolo

13

在我们的情况下,只要用户滚动一下屏幕,问题就会自行解决。因此,以下是我们一直在使用的模拟滚动的修复方法:

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

非常感谢!这就是解决我的iOS 7问题的方法。 - ivkremer

5

根据这篇优秀分析,我在html和body元素的css中使用了以下代码:

html,body{
    -webkit-overflow-scrolling : touch !important;
    overflow: auto !important;
    height: 100% !important;
}

对我来说,它的工作效果很棒。


我刚刚确认了position: fixed; top: 0px的效果非常好。但是,对于bottom: 0px(固定在底部),在iOS 11上无法正常工作。我刚刚升级到iOS 12,现在它完美地运行了。谢谢! - Aidin
这对我不起作用,因为窗口滚动事件不再触发了。 - Vizz85
在iOS 15.5中无法工作。 - thdoan

3
这里有一个使用jQuery的笨办法解决问题:
HTML代码:
<label for="myField">My Field:</label> <input type="text" id="myField" />

<!-- ... other markup here .... -->

<div class="ad_wrapper">my fixed position container</div>

CSS:

.ad_wrapper {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 40px;
    background-color: rgba(0,0,0,0.75);
    color: white;
    text-align: center;
}
.unfixed {
    position: relative;
    left: auto;
    bottom: auto;
}

JS:

$(function () {
    adWrapper = $('.ad_wrapper');

    $(document).on('focusin', 'input, textarea', function() {
        adWrapper.addClass('unfixed');
    })
    .on('focusout', 'input, textarea', function () {
        adWrapper.removeClass('unfixed');
    });
});

3
到目前为止,我尝试的所有解决方案都有一个问题:当 iPhone 显示键盘时,固定的顶部导航栏会消失。如果您希望固定元素在键盘显示时仍保持在相同位置怎么办?下面是一个简单的解决方案,可以实现这一点,并且在页面滚动时保持固定元素固定在顶部(即使焦点仍在输入字段中)。
// Let's assume the fixed top navbar has id="navbar"
// Cache the fixed element
var $navbar = $('#navbar');

function fixFixedPosition() {
  $navbar.css({
    position: 'absolute',
    top: document.body.scrollTop + 'px'
  });
}
function resetFixedPosition() {
  $navbar.css({
    position: 'fixed',
    top: ''
  });
  $(document).off('scroll', updateScrollTop);
}
function updateScrollTop() {
  $navbar.css('top', document.body.scrollTop + 'px');
}

$('input, textarea, [contenteditable=true]').on({
  focus: function() {
    // NOTE: The delay is required.
    setTimeout(fixFixedPosition, 100);
    // Keep the fixed element absolutely positioned at the top
    // when the keyboard is visible
    $(document).scroll(updateScrollTop);
  },
  blur: resetFixedPosition
});

要查看演示,请fork下面的笔并在您的iPhone上以Debug模式查看:

https://codepen.io/thdoan/pen/JWYQeN

这里有一个使用requestAnimationFrame的版本,但似乎没有表现得更好,所以我坚持使用第一个版本,因为它更简单:

https://codepen.io/thdoan/pen/VpvJNX


1
我在粘性标题中添加了一个搜索输入框。focus导致页面滚动到页面顶部。你的解决方案对我不起作用。我正在尝试修复它。有什么想法或提示可能出了什么问题吗? - Kosmonaft
@Kosmonaft,你能提供一个 CodePen 或等效的网站吗? - thdoan
可以的。这是链接(我不知道为什么在CodePen上粘性头部在iPad上不起作用。但在我的本地项目中是粘性的):https://codepen.io/kosmonaft/pen/bWWaMj - Kosmonaft
@Kosmonaft,我无法在Android上重现此问题,并且我在这里找不到使用iPad的人。您可以尝试在Android平板电脑上复制该问题吗?关于标题未粘性,请尝试更改为全页面或调试视图。 - thdoan

1
你需要做的是在用户编辑文本时将body的位置设置为fixed,然后在用户完成后恢复为static。你可以在焦点/模糊上执行此操作(如下所示),或者如果用户正在打开模态框,则可以在模态框打开/关闭时执行此操作。
$("#myInput").on("focus", function () {
    $("body").css("position", "fixed");
});

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

1

已修复 - 在输入搜索文本框后,通过一个 hack 技巧将页眉推回相对固定的位置。这是 iOS 虚拟键盘实现中的一个 bug,因为它会在文本字段上打破固定位置,如果页面可滚动。如果 overflow 被隐藏 / 页面不可滚动,则在执行虚拟键盘时不会破坏固定位置。

感谢您的耐心等待。


21
你好,你能分享一下你的代码吗?还有,“overscroll”是什么意思?你指的是overflow:scroll吗? - drogon
overscroll = 在这个答案中的overflow - Silkster
4
overscroll不是一个属性。 - Patrik Affentranger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接