iPhone Web App - 停止正文滚动

时间:2011-12-13 11:30:58

标签: css web-applications

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

虽然它有效,但如果向上滚动页面顶部,它会显示常用的灰色区域一段时间,然后再滚动

Example

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

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

6 个答案:

答案 0 :(得分:16)

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

bouncefix.js

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

用法:

<强> bouncefix.add(EL)

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

<强> bouncefix.remove(EL)

删除所有负责修复全身弹性反弹的侦听器/观察者。

为什么?

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

  1. 只有在有可滚动内容时才有用。如果你有 空页面,会对身体产生反弹效果。
  2. API没有公开删除侦听器的方法。我的应用会 有多个页面,并且保持所有权利并不合适 当用户在应用程序中移动时附加的侦听器。
  3. 如何?

    它使用与scrollfix类似的方法。当您处于其中一个滚动极值时会发生此问题。在touchstart上,我们会看看我们是处于顶部极端还是底部极端,如果我们处于顶部,则添加1px,如果我们位于底部,则删除1px。

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

答案 1 :(得分:11)

对我有用的是什么:

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

plus(使用jQuery ...)

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

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

实际上,这会捕获文档中的所有touchmove个事件,但如果原始事件是从.scrollable冒出的,我们只需stopPropagation而不是取消事件。

答案 2 :(得分:10)

尝试将它放在JS文件的顶部..

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

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

来源:Stop UIWebView from "bouncing" vertically?

答案 3 :(得分:5)

<强>更新

这个问题对很多人来说都很痛苦,但这是由bjrn创建的可靠解决方案:

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

这最初由ryan发布,以回答我的问题:Prevent touchmove default on parent but not child

我希望能帮助一些人。


原始回答:

我实际上正在研究完全相同的问题而且我遇到过这个问题:

https://github.com/joelambert/ScrollFix

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

希望有所帮助(这绝对帮助了我!) 将:)

答案 4 :(得分:1)

像其他人建议的那样,我编写了一个快速功能,只要滚动到顶部或底部,就会阻止我的滚动div一个像素,以防止整个页面被拖动。这对于我的滚动div来说很好,但是我页面上的固定div仍然容易受到页面拖动的影响。我不小心注意到,当我在滚动div的顶部分层固定的div(由于我的碰撞功能而不再拖动页面)时,触摸拖动事件通过固定div传递到下面的滚动div并且固定的div是no更长的潜在页面拖动器。基于此,我认为可以在后台使用全屏滚动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>

答案 5 :(得分:0)

先前的解决方案建议:

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

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

为了克服这个问题,可以做到以下几点:

  1. 检测感兴趣元素(例如模态)的顶部/底部何时滚动到。
  2. 如果底部滚动到,请使用上述preventDefault技术进行ontouchmove事件,但只有用户尝试进一步向下滚动。
  3. 如果用户尝试向上滚动,请不要再preventDefault
  4. 反之亦然,如果顶部滚动到。
  5. 这是上述逻辑实现的source code

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

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