CSS iPhone Web App - 停止身体滚动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8488447/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 02:22:03  来源:igfitidea点击:

iPhone Web App - Stop body scrolling

cssweb-applications

提问by Oyed

I am creating an iPhone Web Application and you are now, since iOS5, able to use position: fixed; for headers etc. etc.

我正在创建一个 iPhone Web 应用程序,您现在可以从 iOS5 开始使用 position: fixed; 用于标题等。

Although it works, if you scroll up at the top of a page, it displays the usual gray area for a while before you can't scroll anymore

虽然它有效,但如果您在页面顶部向上滚动,它会在您无法再滚动之前显示通常的灰色区域一段时间

Example

例子

Is there a way to stop this scrolling? I've tried things like overflow: hidden; but I can't seem to find anything.

有没有办法阻止这种滚动?我尝试过类似溢出:隐藏;但我似乎找不到任何东西。

P.S. I only want the one thing to stop scrolling, I have a div named #container which I still want to have the ability to scroll.

PS我只想要停止滚动的一件事,我有一个名为#container的div,我仍然希望能够滚动。

采纳答案by Jarid R. Margolin

After reviewing several solutions, I began to create a custom solution:

在查看了几个解决方案后,我开始创建自定义解决方案:

bouncefix.js

弹跳修复.js

http://jaridmargolin.github.io/bouncefix.js/

http://jaridmargolin.github.io/bouncefix.js/

Usage:

用法:

bouncefix.add(el)

弹跳fix.add(el)

Apply fix so that the given element no longer causes a full body elastic bounce when scrolling at its extremes.

应用修复,以便给定元素在其极端滚动时不再导致全身弹性反弹。

bouncefix.remove(el)

弹跳fix.remove(el)

Remove all listeners/observers responsible for fixing the full body elastic bounce.

移除所有负责修复全身弹性反弹的听众/观察者。

Why?

为什么?

Scrollfixwas a good start, however I noticed several problems:

Scrollfix是一个好的开始,但是我注意到了几个问题:

  1. It only worked when there was scrollable content. If you had an empty page, the bounce effect on the body would occur.
  2. The API did not expose a method to remove the listeners. My app will have multiple pages, and it didn't feel right to keep all of the listeners attached as the user moved around the app.
  1. 它仅在有可滚动内容时才有效。如果你有一个空页面,身体上的反弹效果就会发生。
  2. API 没有公开删除侦听器的方法。我的应用程序将有多个页面,当用户在应用程序周围移动时,让所有侦听器都保持连接感觉不合适。

How?

如何?

It uses a similar approach to that of scrollfix. The problem occurs when you are at one of the scrolling extremes. On touchstart, we look to see if we are at the top extreme or bottom extreme, adding 1px if we are at the top, and removing 1px if we are at the bottom.

它使用与 scrollfix 类似的方法。当您处于滚动极端之一时会出现问题。在 touchstart 上,我们查看我们是在顶部极端还是底部极端,如果我们在顶部,则添加 1px,如果我们在底部,则删除 1px。

Unfortunately, this trick only works if we are able to set the scrollTop value. If the content is not yet scrollable, for example, you only have 1 list item, the whole body will again scroll. Bouncefix.js will take care of all of this behind the scenes by using event delegation and checking the scrollHeight against the offsetHeight anytime touchstart is triggered. In the case that there is no scrollable content, all scrolling on the container is blocked with e.preventDefault();

不幸的是,这个技巧只有在我们能够设置 scrollTop 值时才有效。如果内容尚不可滚动,例如,您只有 1 个列表项,则整个正文将再次滚动。Bouncefix.js 将通过使用事件委托并在触发 touchstart 时根据 offsetHeight 检查 scrollHeight 来在幕后处理所有这些。在没有可滚动内容的情况下,容器上的所有滚动都被 e.preventDefault() 阻止;

回答by Jiaaro

what worked for me:

什么对我有用:

html, body, .scrollable {
    overflow: auto; 
    -webkit-overflow-scrolling: touch;
}

plus (using jQuery...)

加上(使用jQuery...)

$(function() {
  $(document).on("touchmove", function(evt) { evt.preventDefault() });
  $(document).on("touchmove", ".scrollable", function(evt) { evt.stopPropagation() });
});

it's important that the evt.stopPropagation()call is using a delegate since it's also caught on the documentbut cancelled at the last second.

evt.stopPropagation()调用使用委托很重要,因为它也在文档中被捕获但在最后一秒被取消。

In effect this catches all touchmoveevents on the document but if the original event was bubbled up from a .scrollablewe simply stopPropagationinstead of cancelling the event.

实际上,这会捕获touchmove文档上的所有事件,但是如果原始事件是从 a 冒泡出来的,.scrollable我们只是简单地stopPropagation而不是取消该事件。

回答by Ben Clayton

Try putting this at the top of your JS file..

尝试将其放在 JS 文件的顶部。

document.ontouchmove = function(event){
    event.preventDefault();
}

This'll stop you being able to scroll your page at all, so you won't be able to see the 'grey area' at the top.

这将完全阻止您滚动页面,因此您将无法看到顶部的“灰色区域”。

Source: Stop UIWebView from "bouncing" vertically?

来源:阻止 UIWebView 垂直“弹跳”?

回答by will

Update:

更新:

This issue has been a pain for lots of people, but here is a solid solution created by bjrn:

这个问题一直困扰着很多人,但这里是bjrn创建的可靠解决方案:

Demo:http://rixman.net/demo/scroll/
And there's a discussion about it here: https://github.com/joelambert/ScrollFix/issues/2

演示:http : //rixman.net/demo/scroll/
这里有一个关于它的讨论:https: //github.com/joelambert/ScrollFix/issues/2

This was originally posted by ryanin answer to a question of mine: Prevent touchmove default on parent but not child.

这最初是由ryan在回答我的一个问题时发布的:Prevent touchmove default on parent but not child

I hope that helps some people.

我希望这能帮助一些人。



Original answer:

原答案:

I'm actually looking into the exact same issue and I've come across this:

我实际上正在研究完全相同的问题,但我遇到了这个问题:

https://github.com/joelambert/ScrollFix

https://github.com/joelambert/ScrollFix

I've tried it out and it works nearly perfectly. If you copy all the code into a demo and give it a go on iOS you'll not see the grey background unless you grab the black bar and try to scroll that. However, it should be pretty easy to use the code that Ben supplied to prevent that happening ( preventDefault() ).

我已经试过了,它几乎完美地工作。如果您将所有代码复制到演示中并在 iOS 上试一试,除非您抓住黑条并尝试滚动它,否则您将看不到灰色背景。但是,使用 Ben 提供的代码来防止这种情况发生应该很容易( preventDefault() )。

Hope that helps (It's definitely helped me!) will :)

希望有帮助(这肯定对我有帮助!)会:)

回答by Shawn

Like others suggested I wrote a quick function that bumps my scrolling div one pixel whenever it is scrolled to the top or bottom to prevent the entire page from dragging. That's fine for my scrolling div but the fixed divs on my page were still susceptible to page drag. I accidentally noticed that when I layered a fixed div on top of my scrolling div (which no longer dragged the page because of my bump function) the touch drag events were passed through the fixed div to the scrolling div underneath and that fixed div was no longer a potential page dragger. Based on that I figured it might be possible to use a full screen scrolling div in the background as the foundation for the entire page so that all dragging would be pass through and my actual elements on top will be safe. The foundation div needs to actually scroll so I placed a filler div inside of it and made it slightly larger to guarantee it scrolls. And it worked! Below is an example using this idea to prevent page dragging. Sorry if this is obvious or already posted but I didn't see this anywhere else and it really improved my web app. Please try it out and let me know if it helps.

就像其他人建议的那样,我编写了一个快速函数,每当我的滚动 div 滚动到顶部或底部时,它就会将我的滚动 div 增加一个像素,以防止整个页面被拖动。这对我的滚动 div 很好,但我页面上的固定 div 仍然容易受到页面拖动的影响。我意外地注意到,当我在滚动 div 上分层固定 div(由于我的凹凸功能不再拖动页面)时,触摸拖动事件通过固定 div 传递到下面的滚动 div 并且该固定 div 没有不再是潜在的页面拖动器。基于这一点,我认为可能可以在后台使用全屏滚动 div 作为整个页面的基础,以便所有拖动都通过,并且我在顶部的实际元素将是安全的。基础 div 需要实际滚动,所以我在其中放置了一个填充 div 并使其稍大以保证它滚动。它奏效了!下面是一个使用这个想法来防止页面拖动的示例。对不起,如果这很明显或已经发布,但我在其他任何地方都没有看到它,它确实改进了我的网络应用程序。请尝试一下,如果有帮助,请告诉我。

<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">

<style>
.myDiv {
    position:absolute;
    left:0;
    width:100%;
    color:white;
}

.myDiv.hidden {
    top:0;
    height:100%;
    -webkit-overflow-scrolling:touch;
    overflow-y:scroll;
}

.myDiv.title {
    top:0;
    height:30%;
    background-color:#6297BC;
}

.myDiv.scroll {
    bottom:0;
    height:70%;
    -webkit-overflow-scrolling:touch;
    overflow-y:scroll;
    background-color:#ADADAD;
}
</style>

<script>
function setup() {  
    hiddenScrollingDiv.addEventListener("scroll", preventWindowScroll);
    visibleScrollingDiv.addEventListener("scroll", preventWindowScroll);
    hiddenScrollingDiv.style.height=window.innerHeight; 
    visibleScrollingDiv.style.height=parseInt(window.innerHeight*.7)+1; 
    fillerDiv.style.height=window.innerHeight+2;
    hiddenScrollingDiv.scrollTop=1;
    visibleScrollingDiv.scrollTop=1;
}

function preventWindowScroll(evt) {
    if (evt.target.scrollTop==0) evt.target.scrollTop=1;
    else if (evt.target.scrollTop==(evt.target.scrollHeight-parseInt(evt.target.style.height))) evt.target.scrollTop=evt.target.scrollHeight-parseInt(evt.target.style.height)-1;
}
</script>
</head>

<body onload="setup()">
<div id="hiddenScrollingDiv" class="myDiv hidden"><div id="fillerDiv"></div></div>
<div id="visibleTitleDiv" class="myDiv title"><br><center>Non-scrolling Div</center></div>

<div id="visibleScrollingDiv" class="myDiv scroll">
<ul>
    <li style="height:50%">Scrolling Div</li>
    <li style="height:50%">Scrolling Div</li>
    <li style="height:50%">Scrolling Div</li>
</ul>
</div>

</body>
</html>

回答by Will Po

A previous solution suggested :

以前的解决方案建议:

document.ontouchmove = function(event){
    event.preventDefault();
}

However, this also stops the scrolling for the element of interest.

但是,这也会停止滚动感兴趣的元素。

In order to overcome this, the following can be done:

为了克服这个问题,可以采取以下措施:

  1. Detect when the top/bottom of an element of interest (eg. modal) has been scrolled to.
  2. If bottom scrolled to, use the above preventDefaulttechnique for the ontouchmove event, but ONLY IF, the user attempts to scroll down further.
  3. If user attempts to scroll up, don't preventDefaultanymore.
  4. Vice versa applies if top is scrolled to.
  1. 检测何时滚动到感兴趣的元素(例如模态)的顶部/底部。
  2. 如果底部滚动到,preventDefault对 ontouchmove 事件使用上述技术,但仅当用户尝试进一步向下滚动时。
  3. 如果用户尝试向上滚动,请不要preventDefault再尝试了。
  4. 如果滚动到顶部,则反之亦然。

Here's the source codefor an implementation of the above logic.

这是实现上述逻辑的源代码

The npm package can also be downloaded for convenience (tested with vanilla JS/React on iOS mobile/desktop safari as well as Android/Desktop Chrome).

为了方便起见,也可以下载 npm 包(在 iOS 移动/桌面 safari 以及 Android/桌面 Chrome 上使用 vanilla JS/React 进行测试)。

Checkout https://medium.com/jsdownunder/locking-body-scroll-for-all-devices-22def9615177for more of an explanation of the different approaches.

查看https://medium.com/jsdownunder/locking-body-scroll-for-all-devices-22def9615177以获取对不同方法的更多解释。