【问题标题】:A simple solution to prevent scrolling problems mobile safari (iOS)防止滚动问题的简单解决方案移动 safari (iOS)
【发布时间】:2017-07-22 14:17:24
【问题描述】:

考虑以下场景:

你有 2 个可滚动的元素。

  1. 附加到 $(document).scroll() 的一长串项目
  2. 监听 $(".class").scroll() 的单独容器/覆盖层

具有以下 CSS 属性。

body {
overflow-y: scroll;
height: 100%;
}

.class {
height: 100%; /* 50% 20% 200px whatever you may */
position: fixed;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}

换句话说,一个非常标准的设置,在 2017 年应该可以在任何设备上正常工作。错误。

以下是我多年来在使用这种简单设置时遇到的问题,从未找到一个好的、可靠的解决方案:

  1. 当滚动到覆盖层的 顶部底部(高度为 100%)时,覆盖层开始从轻微到极端闪烁,无论所有 iDevice 的 HTML 复杂性如何。 (因为过度滚动的 z-index 问题,或者硬件加速问题,我不知道)。
  2. 在顶部或底部时,覆盖完全停止滚动,以等待 body-scroll 停止过度滚动。
  3. 当容器的滚动错误停止时(同时出现过度滚动),并且用户继续滚动,正文将改为滚动,导致用户体验非常不一致,因为用户现在最终会出现在某个地方正文滚动中的其他内容比打开叠加层之前的内容。为了等待过度滚动停止而不得不停止滚动也很烦人。

  4. 如果容器是 100% 高度,并且没有滚动 - 如果用户启动 滚动,正文将滚动并且滚动条将可见,但是 页面似乎没有滚动,导致用户不一致 经验。

我尝试过的一些解决方案没有成功。

  1. iScroll。 iScroll 通过阻止文档上的任何触摸事件来停止过度滚动问题。但是提供了不一致和糟糕的滚动体验恕我直言。此外,它甚至不再需要了。
  2. 所有其他可以想象的滚动插件。
  3. 事件委托 - 尝试仅为正在交互的元素启用滚动。在桌面上工作。不是移动 Safari。
  4. 可以想象到的每一个 jQuery 滚动辅助工具。轻微的成功,但非常不一致。

似乎过去提出的任何解决方案都以某种方式因“各种原因”而被贬值(听起来不是阴谋。)

几周前我读到,Apple 正在为 滚动 webkit 以使其在所有类型的 在 iPhone 上提供的内容类型。但在那之前,这种简单的设置在移动 Safari 上仍然存在很大问题。

我可能最终想出了一个解决方案。但我很想知道其他人在 2017 年是如何解决这个问题的……

2018 年 WebView 应用更新 虽然 Apple 并未努力解决此问题,但如果您正在构建 webview 应用程序,彻底消除任何问题的绝对最佳解决方案是直接在 Swift 中完全禁用浏览器滚动 (webview)。

当您的 WebView 已加载时,只需使用:

    override func viewDidLoad() {
        super.viewDidLoad()
        wkWebView1.scrollView.isScrollEnabled = false
        wkWebView1.scrollView.bounces = false
}

然后在你的 CSS 中为每个需要滚动的容器单独设置滚动。

请注意,此解决方案将完全禁用 $(document).scroll()。

我希望它对某人有所帮助。

【问题讨论】:

  • 如果您添加了随附的 HTML,那将非常有用。考虑添加一个 sn-p。谢谢
  • 你真的认为有必要吗?就我而言,这是一个广为人知的问题。让我知道你的想法。
  • 是的,我认为。 (3 小时后,你还没有答案..)但我现在要出去了,所以我没用了.. 稍后!
  • 你解决过这个问题吗?我也有同样的问题?
  • 我最终输入了溢出:无;在弹出窗口打开时在 body 和 html 上,并在弹出窗口关闭时保存滚动顶部以将其动画到该滚动顶部。

标签: css swift webview webkit mobile-safari


【解决方案1】:

我将在此处添加评论,因为这看起来像是最近的问题,很好地概述了问题(谢谢!)

我也尝试了几乎你所说的一切,最终找到了解决方案。 基本上,您需要设置主容器和叠加层的大小,将它们都设为fixed 并赋予它们overflow: auto,以便文档本身永远不会滚动

  • 当覆盖关闭时,内容会在主容器内滚动并保持原状。 (将height: 100vh; width: 100vw;top/left/bottom/right: 0;box-sizing: border-box; 一起使用有助于不显眼。)
  • 打开叠加层时,将主容器切换为overflow: hidden,此时叠加层内的内容滚动。同样,文档本身永远不会这样做。

这有一个缺点:地址栏在 iOS 上从不隐藏。我相信这仍然是一种更可取的体验,因为它始终保持一致。

此外,如果您从可滚动区域外开始滚动,则会获得焦点,并且 iOS 的橡皮筋效果会阻止与页面的后续交互,直到完成橡皮筋。 (其他地方有帖子解释了如何解决这个问题——你监控滚动事件,如果元素到达顶部,则将元素向下推 1px,如果在底部,则向上推 1px。)

这是一个演示 (codepen here):

let openBtns = document.getElementsByClassName('open'),
    closeBtns = document.getElementsByClassName('close'),
    overlay = document.getElementById('overlay');


for (let btn of openBtns) {
    btn.onclick = () => {
        document.body.classList.add('overlay-open');
        overlay.setAttribute('aria-hidden', false);
    };
}

for (let btn of closeBtns) {
    btn.onclick = () => {
        document.body.classList.remove('overlay-open');
        overlay.setAttribute('aria-hidden', true);
    };
}
#page, #overlay {
    position: fixed;
    top: 0; bottom: 0; left: 0; right: 0;
    margin: auto;
    box-sizing: border-box;
    overflow: auto;
    font-size: 4em;
    -webkit-overflow-scrolling: touch;
}

#page {
    padding: 1rem 2rem 2rem;
}

.overlay-open > #page {
    position: fixed;
    filter: blur(5px);
    overflow: hidden;
    pointer-events: none;
}

#overlay {
    display: none;
    padding: 2rem;
    font-size: 2em;
}

#overlay > .content {
    position: relative;
    width: 20em;
    margin: auto;
    padding: 0 1rem 1rem;
    background-color: rgba(200, 0, 255, 0.5);
}

.overlay-open > #overlay {
    display: block;
}
<body>
    <div id="page">
        <div class="content">
            <button class="open">Open overlay</button>
            <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>
            <button class="open">Open overlay</button>
        </div>
    </div>
    <div id="overlay" aria-hidden="true">
        <div class="content">
            <button class="close">Close overlay</button>
            <p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.</p>
            <button class="close">Close overlay</button>
        </div>
    </div>
</body>

(请注意,这里有一些 CSS,只有 sn-ps 在这里或 Codepen 上才有意义,基本上所有与位置/溢出无关的内容都是为了展示;应该很容易弄清楚,但是随时要求澄清。)

【讨论】:

  • 是的,这基本上也是我解决它的方法,同时保存主容器的滚动位置,因为禁用滚动时页面会自动滚动到顶部。然而,它在移动设备上并不是一个完美的解决方案,我发现 iOS 设备上的身体惯性仍然处于活动状态。因此,如果您向下滚动到底部,请等到反弹效果完全停止。向下滚动然后再次向上滚动,整个视图卡住了。从我所做的所有研究来看。由 Apple 来解决这个问题,因为根本没有办法解决它。
  • 不需要任何额外的 JS,据我所知,在该示例中页面不会跳回开始。这是我之前遇到的一个问题,不幸的是我不记得解决它的确切内容,但无论如何我相信实施没有那个问题。 (编辑)至于惯性,是的,这就是我提到的橡皮筋——但就像我说的,防止元素实际到达顶部/底部的 hacky 方法应该会有所帮助吗?
  • 至少在移动浏览器上,当你溢出时页面会跳回到scrollTop 0:隐藏;在一个元素上......但它看起来不像在桌面版本上发生。
  • 您是否尝试过在您的手机上运行我发布的示例或打开 codepen 的完整视图?在我的 iPhone (iOS 11.2.2) 上,无论是在 Firefox 还是 Safari 上,页面都不会跳回。与实施此操作的生产网站相同。
  • positin: fixed 是通往地狱的捷径。一旦你遇到这个错误stackoverflow.com/a/10170170/800613,你就会发现-webkit-transform: translate3d(0,0,0) + position: fixed 的组合有多可怕。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 2015-08-25
  • 2014-05-18
相关资源
最近更新 更多