防止移动 safari 滚动问题的简单解决方案(iOS)

Cra*_*tor 6 css webkit mobile-safari webview swift

考虑以下场景:

\n\n

您有 2 个可滚动元素。

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

在此输入图像描述

\n\n

具有以下 CSS 属性。

\n\n
body {\noverflow-y: scroll;\nheight: 100%;\n}\n\n.class {\nheight: 100%; /* 50% 20% 200px whatever you may */\nposition: fixed;\noverflow-y: scroll;\n-webkit-overflow-scrolling: touch;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

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

\n\n
    \n
  1. 当滚动到顶部底部时,叠加层开始从轻微到极端闪烁,无论所有 iDevice 上的 HTML 复杂程度如何。(由于过度滚动的 z-index 问题或硬件加速问题,我不知道)。
  2. \n
  3. 当位于顶部或底部时,覆盖层的滚动完全停止,以等待主体滚动停止过度滚动。
  4. \n
  5. 当容器的滚动错误地停止时(同时出现过度滚动),并且用户继续滚动,正文将滚动,从而导致用户体验非常不一致,因为用户现在将到达正文滚动中的其他位置与打开覆盖层之前相比。必须停止滚动以等待过度滚动停止也很烦人。

  6. \n
  7. 如果容器高度为 100%,并且没有滚动 \xe2\x80\x93 如果用户开始\n滚动,则正文将滚动并且滚动条将可见,但\n页面似乎没有\n滚动,从而导致用户体验不一致\n。

  8. \n
\n\n

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

\n\n
    \n
  1. 滚动。iScroll 通过防止文档上的任何触摸事件来阻止过度滚动问题。但恕我直言,提供了不一致且糟糕的滚动体验。此外,甚至不再需要它了。
  2. \n
  3. 所有其他可以想象到的滚动插件。
  4. \n
  5. 事件委托 \xe2\x80\x93 尝试仅为正在交互的元素启用滚动。适用于桌面。不是移动游猎。
  6. \n
  7. 所有可以想象到的 jQuery 滚动辅助工具。取得了一定的成功,但非常不一致。
  8. \n
\n\n

似乎过去提出的任何解决方案都因“各种原因”而被贬低(无意听起来阴谋论。)

\n\n
\n

几周前我读到,Apple 正在对 webkit 的滚动进行更新,以使其在 iPhone 上提供的所有类型的内容类型中更加同质。但在那之前,这个简单的设置在移动 Safari 上仍然存在很大问题。

\n
\n\n

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

\n\n

WebView 应用程序更新 2018 \n虽然 Apple 没有努力解决这个问题,但绝对是彻底根除任何问题的最佳解决方案绝对最佳解决方案是直接在 Swift 中完全禁用浏览器滚动(WebView)。

\n\n

当你的 WebView 加载完毕后,只需使用:

\n\n
    override func viewDidLoad() {\n        super.viewDidLoad()\n        wkWebView1.scrollView.isScrollEnabled = false\n        wkWebView1.scrollView.bounces = false\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

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

\n\n

我希望它能帮助某人。

\n

Acc*_*ent 4

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

\n\n

我也尝试了您所说的几乎所有内容,并最终找到了解决方案。\n基本上,您需要设置主容器和覆盖层的大小,使它们同时存在fixed并给出它们overflow: auto,以便文档本身永远不会滚动

\n\n
    \n
  • 当覆盖层关闭时,内容会在主容器内滚动并保持不变。(使用height: 100vh; width: 100vw;top/left/bottom/right: 0;有助于box-sizing: border-box;使其不引人注目。)
  • \n
  • 当您打开覆盖层时,您将主容器切换到overflow: hidden,此时覆盖层内的内容会滚动。同样,文档本身从来没有这样做过。
  • \n
\n\n

这有一个缺点:地址栏在 iOS 上永远不会隐藏。我相信这仍然是一种更好的体验,因为它始终如一。

\n\n

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

\n\n

这是一个演示(此处为 codepen):

\n\n

\r\n
\r\n
let openBtns = document.getElementsByClassName(\'open\'),\r\n    closeBtns = document.getElementsByClassName(\'close\'),\r\n    overlay = document.getElementById(\'overlay\');\r\n\r\n\r\nfor (let btn of openBtns) {\r\n    btn.onclick = () => {\r\n        document.body.classList.add(\'overlay-open\');\r\n        overlay.setAttribute(\'aria-hidden\', false);\r\n    };\r\n}\r\n\r\nfor (let btn of closeBtns) {\r\n    btn.onclick = () => {\r\n        document.body.classList.remove(\'overlay-open\');\r\n        overlay.setAttribute(\'aria-hidden\', true);\r\n    };\r\n}
Run Code Online (Sandbox Code Playgroud)\r\n
#page, #overlay {\r\n    position: fixed;\r\n    top: 0; bottom: 0; left: 0; right: 0;\r\n    margin: auto;\r\n    box-sizing: border-box;\r\n    overflow: auto;\r\n    font-size: 4em;\r\n    -webkit-overflow-scrolling: touch;\r\n}\r\n\r\n#page {\r\n    padding: 1rem 2rem 2rem;\r\n}\r\n\r\n.overlay-open > #page {\r\n    position: fixed;\r\n    filter: blur(5px);\r\n    overflow: hidden;\r\n    pointer-events: none;\r\n}\r\n\r\n#overlay {\r\n    display: none;\r\n    padding: 2rem;\r\n    font-size: 2em;\r\n}\r\n\r\n#overlay > .content {\r\n    position: relative;\r\n    width: 20em;\r\n    margin: auto;\r\n    padding: 0 1rem 1rem;\r\n    background-color: rgba(200, 0, 255, 0.5);\r\n}\r\n\r\n.overlay-open > #overlay {\r\n    display: block;\r\n}
Run Code Online (Sandbox Code Playgroud)\r\n
<body>\r\n    <div id="page">\r\n        <div class="content">\r\n            <button class="open">Open overlay</button>\r\n            <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>\r\n            <button class="open">Open overlay</button>\r\n        </div>\r\n    </div>\r\n    <div id="overlay" aria-hidden="true">\r\n        <div class="content">\r\n            <button class="close">Close overlay</button>\r\n            <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>\r\n            <button class="close">Close overlay</button>\r\n        </div>\r\n    </div>\r\n</body>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

(请注意,其中有一些 CSS 只需要让代码片段在此处或 Codepen 上有意义,基本上所有与位置/溢出无关的内容都是为了显示;应该很容易弄清楚但请随时要求澄清。)

\n