【问题标题】:IOS Safari: unwanted scroll when keyboard is opened and body scroll is disabledIOS Safari:打开键盘并禁用正文滚动时不需要滚动
【发布时间】:2019-10-14 12:20:09
【问题描述】:

有一种已知的技术可以在打开模式窗口时禁用页面滚动。

CSS:

html {
  height: 100%;
}

body.disable-scroll {
  position: fixed;
  height: 100%;
  overflow: hidden;
}

HTML:

<!DOCTYPE html>
<html>

<head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
    <meta content="width=device-width, initial-scale=1.0, user-scalable=no" name="viewport">
</head>

<body class="disable-scroll">
    <div class="page-content">
        <input type="text">
        ... content ...
    </div>
</body>

</html>

但在 IOS Safari 上,打开虚拟键盘后会启用滚动。它甚至比window.innerHeight + window.scrollX 滚动更多。页面底部出现一些空白。

编者网址
https://codesandbox.io/s/condescending-snow-skuo5?fontsize=14

在 iPhone 上检查的全屏网址
https://skuo5.codesandbox.io/
只需在 iPhone 或 XCode 中打开 IOS 12+ 尝试滚动,然后专注于输入并再次尝试滚动。

【问题讨论】:

    标签: html ios css


    【解决方案1】:

    只是为到达这里的人提供一些信息。

    Safari 认为这是一个功能。 有一个错误报告 here(让他们知道你不喜欢这个“功能”=])。

    当您打开键盘时,浏览器的window 会向上移动,并且您的内容会被隐藏,因为window 不在屏幕上。其他奇怪的行为也可能发生,就像 OP 显示的那样。

    查看这篇博文了解更多细节和更多奇怪行为的例子(我从上面复制了上面的图片):https://blog.opendigerati.com/the-eccentric-ways-of-ios-safari-with-the-keyboard-b5aa3f34228d

    【讨论】:

    • safari 是一个新的 IE,这就是人们所说的
    • 这里(至少)有 2 个 Safari 错误 - 您链接到的错误与收回浏览器 chrome 和 100vh 有关,此处解释得更好:developers.google.com/web/updates/2016/12/url-bar-resizing 第二个错误与 on- 有关屏幕键盘处理,以及 Safari 在键盘可见时添加滚动高度的事实,并且无法控制此行为(并且没有调整大小事件或其他事件来检测它)。
    【解决方案2】:

    刚刚经历了繁琐的搜索,这似乎是 iPhone 的问题,正如您在以下文章中指出的那样:https://blog.opendigerati.com/the-eccentric-ways-of-ios-safari-with-the-keyboard-b5aa3f34228d

    因此,您肯定无法使用 css 来做到这一点。

    但这并不妨碍你使用 JQuery 和 Javascript >:)

    对于您的场景,这是一个不整洁的解决方法。也测试了多个文本框仅在 iPhone 上

    document.getElementById("app").innerHTML = `
    <div class="page-content">
    <input type="text" 
    onfocus="disableScrolling(this)" 
    onfocusout="enableScrolling(this)">
      <p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p>
      <input type="text" 
      id="text2"
    onfocus="disableScrolling(this)" 
    onfocusout="enableScrolling(this)">
      <p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p>
    </div>`;
    
    var currentElem;	
    
    function stopScroll() 
    {
        if(currentElem)
        {
            var top = $("input:focus").offset().top;
            $('html, body').stop().animate({
                scrollTop: top
            }, 500, function(){});
        }
    }
    
    function disableScrolling(elem) 
    {
        currentElem = elem;
        document.addEventListener("touchend", stopScroll);
        setTimeout(function()
        {
            stopScroll();
        },10);
    }
    
    function enableScrolling() 
    {
        currentElem = undefined;
        document.removeEventListener("touchend", stopScroll);
    }
    html {
      height: 100%;
      scroll-behavior: smooth;
    }
    
    body.disable-scroll {
      position: fixed;
      height: 100%;
      overflow: hidden;
    }
    
    .page-content {
      background: #ccc;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <body class="disable-scroll">
      <div id="app"></div>
      <div>End of body</div>
    </body>
    简而言之,我做了什么。

    问题:用户可以在关注textbox时滚动离开

    假设,

    解决方案:允许用户滚动到任何他想要的地方,一旦他完成了,就把他顺利地带回到你想要的地方; input:focused:p

    注意:我使用 JQuery 使事情变得更简单。如果你想使用纯javascript,你可以找到具体代码的替换。

    【讨论】:

    • 感谢您的帖子,最好只滚动回焦点输入!只有两件事:在答案本身中添加相关代码会很好,这样当您的链接失效时,解决方案就不会消失。另外,我不太确定为什么你会建议人们使用 jQuery 而不是 vanilla javascript。现在真的不再需要 jQuery 了。
    • Lolzz 我是一个老学生:ppp 我在最初的日子里在 JQuery 中工作过很多次,而且我也很懒惰 >.$("#target"); 而不是document.getElementById("target");(更短的代码长度);) JQuery jus 使编码变得简单:) 在this site 中查看“CODE”是的,vanilla js 可以做一些事情,但它会使大量代码复杂化很多次。就像在答案中使用 offset()animate() 会增加代码长度并使代码随着时间的推移变得难以管理:) P.S:编辑了建议顺便说一句;)
    • 我明白你的意思,但是使用 jquery 需要你加载整个库,而普通 JS 不需要。你不能假设现在每个人都在使用 jQuery。做老派并不是写只适用于一部分观众而不是更广泛范围的答案的借口(除非该问题被特别标记为jquery
    • 冷静兄弟。我不擅长我的沟通技巧>.
    【解决方案3】:

    我在我的一个项目中这样做了...

    当你打开键盘时,在身体上使用它

    $(body).bind('touchmove', function (e) {
        e.preventDefault()
    });
    

    当你想再次滚动时解开它

    $(body).unbind('touchmove');
    

    如果将它与 height:100% 或 100vh 和 overflow:hidden 结合使用。它应该工作。

    【讨论】:

    • 在这篇旧文章benfrain.com/preventing-body-scroll-for-modals-in-ios 中,他们为模态窗口建议了相同的方法。不幸的是,它在 iPhone iOS13 上对我不起作用。当键盘向下时,没有滚动条,完全没问题,但是键盘一出现,就不再控制身体高度了。
    • @KurtLagerbier 你有没有在 iOS 13 上找到解决这个问题的方法?
    • @Clifton 不,很遗憾没有。我为此花了很多时间,但没有找到合适的解决方案。在 Android 上它工作得很好,但 iOS13 想要一个滚动条。
    • @KurtLagerbier 有同样的问题。对于 android 它可以,但对于 iOS 则不行。是的,一旦键盘出现在那里,就无法控制身高。
    • 我希望 Web 也有这样的东西,就像 React Native 中一样:reactnative.dev/docs/keyboardavoidingview
    【解决方案4】:

    你能试试这个css吗..

    html {
      height: 100%;
    }
    
    body.disable-scroll {
      position: fixed;
      top:0;
      bottom:0;
      left:0;
      right:0;
      height: 100vh;
      overflow: hidden;
    }
    

    【讨论】:

    • 没有为我修复它。 Safari 在键盘打开时仍然允许滚动。在 XS 上测试。
    • 请阅读此blog。希望能帮助你理解。
    猜你喜欢
    • 2020-12-06
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 2022-10-09
    • 1970-01-01
    相关资源
    最近更新 更多