禁用Safari中的弹性滚动

61
我想禁用Safari(OSX Lion)中的弹性滚动/反弹效果。 我发现解决方案是在CSS中为body设置“overflow:hidden”,但正如预期的那样,它只会禁用滚动条,因此,如果网站比屏幕“长”,你将无法滚动! 欢迎任何解决方案或提示!谢谢!

我很好奇这个有什么需求。让系统自己做它的事情,通常是我的座右铭。 - Alan H.
11
这是针对单页应用程序的,它们被设计得更像桌面应用程序。 - william44isme
4
这是一个没有征得我们同意的设计决策,它并不适合所有可能的Web应用程序。 - Dom Vinyard
只需在body中创建一个容器来包含所有内容,并保持overflow:hidden;即可。 - www139
弹性滚动严重干扰setTimeout的性能(至少在Chrome中)-如果您正在进行WebAudio实时调度,则禁用弹性滚动可以减少掉帧的风险。 - stephband
实际上,撤销上述操作也无济于事。即使您禁用了弹性滚动,当滚动超出页面限制时(即使页面内容不移动),setTimeout仍然会表现不良。 - stephband
9个回答

76

通过应用以下CSS,您可以更普遍地实现此目标:

html,
body {
  height: 100%;
  width: 100%;
  overflow: auto;
}

这允许您的任何内容在 body 中变得可滚动,但请注意,触发 scroll 事件的滚动上下文现在是 document.body,而不是 window


21
应用这个 CSS 会移除 iOS 上的惯性滚动,请别忘记在 body 中添加 -webkit-overflow-scrolling: touch 以重新启用 iOS 上的惯性滚动。 - Bobby
6
重新启用这个... 在iOS 7上(使用Chrome或Safari浏览器)好像无法正常工作。虽然页面可以按预期滚动,但一旦到达边缘,HTML滚动似乎会接管控制。 - Yaron
4
"-webkit-overflow-scrolling: touch;" 看起来重新启用了弹性滚动。另外,使用这个解决方案后,"document.body.scrollTop"、"window.pageYOffset" 和 "window.scrollY" 不再提供页面滚动的距离值,它们保持为 0。我该如何找到这个值? - Phedg1
13
对我完全没用。 - Corey
5
жңҖдҪіи§ЈеҶіж–№жЎҲ https://www.bram.us/2016/05/02/prevent-overscroll-bounce-in-ios-mobilesafari-pure-css/жң¬ж–Үд»Ӣз»ҚдәҶеҰӮдҪ•дҪҝз”ЁзәҜCSSжқҘйҳІжӯўiOS MobileSafariдёӯзҡ„ж»ҡеҠЁеҸҚеј№ж•ҲжһңгҖӮиҝҷжҳҜйҖҡиҝҮдҪҝз”ЁCSSеұһжҖ§overscroll-behaviorе’Ң-webkit-overflow-scrollingжқҘе®һзҺ°зҡ„гҖӮиҝҷз§Қж–№жі•жӣҙеҠ з®ҖжҙҒиҖҢдё”жӣҙжҳ“дәҺз»ҙжҠӨпјҢеӣ дёәе®ғдёҚйңҖиҰҒJavaScriptжқҘе®һзҺ°гҖӮ - angry kiwi
显示剩余11条评论

15
如果你在<body>元素上使用overflow:hidden技巧,为了恢复正常的滚动行为,你可以在该元素内部绝对定位一个<div>元素,并使用overflow:auto来实现滚动。我认为这是最好的选择,而且只需要使用css就可以轻松实现!或者,你也可以尝试使用jQuery:
$(document).bind(
'touchmove',
function(e) {
e.preventDefault();
}
);

在JavaScript中相同:

document.addEventListener(
'touchmove',
function(e) {
e.preventDefault();
},
false
);

最后一个选项,查看iPad Safari:禁用滚动和反弹效果?


1
谢谢,CSS解决方法可行!我希望可能有一个JavaScript/jQuery的解决方案,因为这个对我来说不起作用。我认为这只适用于iOS设备。如果我错了,请纠正我。 - Fabian
4
回答有些复杂。要针对OS X进行操作,只需在html和body元素上使用overflow: hidden即可。OS X没有“touchmove”事件,这就是所询问的操作系统。 - Matthew
如果你正在从jQuery过渡,不要忘记以下内容:`document.querySelector('div');` `document.querySelectorAll('.someClass');` `document.querySelector('#someID');` - neaumusic

12

overflow:hidden;-webkit-overflow-scrolling:touch在iOS Safari 8.1上无法很好地工作,因为固定的标题会超出可见区域。

gif

正如@Yisela所说,CSS应该放在.container中(即<body>下面的<div>)。 这似乎没有问题(至少在safari iOS 8.1上)

gif

我已经将演示放在我的博客上:http://tech.colla.me/en/show/disable_elastic_scroll_on_iOS_safari


1
链接已经失效了 :( - Oleksandr Danylchenko

12

我在iPad上解决了它。如果你在OSX上也试试看。

body,html { position:fixed; }

仅在内容小于屏幕或使用某些布局框架(例如我的Angular Material)时才有效。

在Angular Material中,非常棒的一点是您可以禁用整个页面的超滚动效果,但内部部分<md-content>仍然可以滚动。


我还必须添加 body,html {width:100%;} 以便在IE11中正确呈现。 :( - Martin
这对我也起作用了。 - Prasad Gayan

5
我制作了一个禁用所有站点的浏览器扩展程序。为此,我使用了三种技术:纯CSS、纯JS和混合技术。
CSS版本与上述解决方案类似。JS版本大致如下:
var scroll = function(e) {
    // compute state
    if (stopScrollX || stopScrollY) {
        e.preventDefault();              // this one is the key
        e.stopPropagation();
        window.scroll(scrollToX, scrollToY);
    }
}

document.addEventListener('mousewheel', scroll, false);

CSS方法适用于使用position:fixed元素并让浏览器进行滚动的情况。如果某些其他JS依赖于window(例如事件),则需要使用JS方法,因为它会在边缘停止事件传播,但需要通过合成非边缘组件的滚动来实现;缺点是它会阻止某些类型的滚动发生(这些使用CSS方法可以正常工作)。混合方法尝试采用混合方法,当滚动到边缘时选择性禁用方向溢出(CSS)和(JS),理论上可以在两种情况下工作,但目前还没有完全达到极限。因此,根据网站的实现方式,需要选择一种方法。如果需要更多细节,请参见这里:https://github.com/lloeki/unelastic

4

我尝试了所有"overflow"的解决方案,但都不起作用。我正在使用jQuery编写JavaScript视觉差效果。在OSX上的Chrome和Safari浏览器中,弹性/橡皮筋效果会破坏我的滚动数字,因为它实际上滚动超过文档的高度,并使用越界数字更新窗口变量。我需要检查滚动量是否大于实际文档的高度,像这样:

$(window).scroll(
    function() {
        if ($(window).scrollTop() + $(window).height() > $(document).height()) return;
        updateScroll(); // my own function to do my parallaxing stuff
    }
);

3

您可以检查滚动偏移是否在边界内。如果超出范围,将其设置回来。

var scrollX = 0;
var scrollY = 0;
var scrollMinX = 0;
var scrollMinY = 0;
var scrollMaxX = document.body.scrollWidth - window.innerWidth;
var scrollMaxY = document.body.scrollHeight - window.innerHeight;

// make sure that we work with the correct dimensions
window.addEventListener('resize', function () {
  scrollMaxX = document.body.scrollWidth - window.innerWidth;
  scrollMaxY = document.body.scrollHeight - window.innerHeight;
}, false);

// where the magic happens
window.addEventListener('scroll', function () {
  scrollX = window.scrollX;
  scrollY = window.scrollY;

  if (scrollX <= scrollMinX) scrollTo(scrollMinX, window.scrollY);
  if (scrollX >= scrollMaxX) scrollTo(scrollMaxX, window.scrollY);

  if (scrollY <= scrollMinY) scrollTo(window.scrollX, scrollMinY);
  if (scrollY >= scrollMaxY) scrollTo(window.scrollX, scrollMaxY);
}, false);

http://jsfiddle.net/yckart/3YnUM/


这会在我们的iPad上引起严重的闪烁,同时阻止页面向上/向下滚动。 - tomazahlin
2
@tomazahlin...这就是一个downvote的理由吗?真的吗?! - yckart
抱歉,但解决方案本身并不好。它只应用于桌面电脑上。现在非常流行的移动设备使用这种方法会出现问题。因此,我建议您在代码周围添加某种检查,我想这样就可以了。 - tomazahlin
2
@tomazahlin 抱歉,但是...这里的大部分内容只是为了解释某些东西“可能”如何工作。大多数代码示例都不是即用型的,您需要深入代码并选择您感兴趣的部分。如果有什么不符合您的需求,请深入挖掘并修复它(也许,开源它?!)。 - yckart

1

有很多情况下上述CSS解决方案并不适用。例如,在同一页上有一个透明的固定页眉和粘性页脚。为了防止Safari中的顶部弹跳影响页面,导致全屏幻灯片闪烁,可以使用以下方法。

    if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {

        $window.bind('mousewheel', function(e) {

            if (e.originalEvent.wheelDelta / 120 > 0) {

                if ($window.scrollTop() < 2) return false;
            } 
        });

    }

用户代理侦查很恶心。 - Dom Vinyard
3
同意,那么也许可以提供一个解决方案吗? - Kieran
所有的兔子洞,但被接受的答案是最宽敞的一个。 - Dom Vinyard

1

以上解决方案都不适用于我,但是我将我的内容包装在一个div(#outer-wrap)中,然后使用以下CSS:

body {
   overflow: hidden;
}
#outer-wrap {
    -webkit-overflow-scrolling: touch;
     height: 100vh;
     overflow: auto;
}

显然,这仅适用于支持视口宽度/高度的浏览器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接