I'm working on an iPad-based web app, and need to prevent overscrolling so that it seems less like a web page. I'm currently using this to freeze the viewport and disable overscroll:
我正在开发一个基于ip的web应用程序,需要防止过度滚动,这样它看起来就不像一个网页了。我现在用这个来冻结viewport和禁用overscroll:
document.body.addEventListener('touchmove',function(e){
e.preventDefault();
});
This works great to disable overscroll but my app has several scrollable divs, and the above code prevents them from scrolling.
这对于禁用滚动效果很好,但我的应用程序有几个可滚动div,上面的代码阻止它们滚动。
I'm targeting iOS 5 and above only so I've avoided hacky solutions like iScroll. Instead I'm using this CSS for my scrollable divs:
我的目标是iOS 5和以上版本,所以我避免了像iScroll这样的陈腐解决方案。相反,我使用这个CSS为我的可滚动divs:
.scrollable {
-webkit-overflow-scrolling: touch;
overflow-y:auto;
}
This works without the document overscroll script, but doesn't solve the div scrolling problem.
这可以在没有文档覆盖脚本的情况下工作,但不能解决div滚动问题。
Without a jQuery plugin, is there any way to use the overscroll fix but exempt my $('.scrollable') divs?
如果没有jQuery插件,是否有办法使用overscroll修复功能,但可以免除$('.scrollable') divs?
EDIT:
编辑:
I found something that's a decent solution:
我找到了一个不错的解决办法:
// Disable overscroll / viewport moving on everything but scrollable divs
$('body').on('touchmove', function (e) {
if (!$('.scrollable').has($(e.target)).length) e.preventDefault();
});
The viewport still moves when you scroll past the beginning or end of the div. I'd like to find a way to disable that as well.
当您滚动到div的开头或结尾时,viewport仍然会移动。我也想找到一种禁用它的方法。
14 个解决方案
#1
84
This solves the issue when you scroll past the beginning or end of the div
当您滚动到div的开头或结尾时,这就解决了这个问题
var selScrollable = '.scrollable';
// Uses document because document will be topmost level in bubbling
$(document).on('touchmove',function(e){
e.preventDefault();
});
// Uses body because jQuery on events are called off of the element they are
// added to, so bubbling would not work if we used document instead.
$('body').on('touchstart', selScrollable, function(e) {
if (e.currentTarget.scrollTop === 0) {
e.currentTarget.scrollTop = 1;
} else if (e.currentTarget.scrollHeight === e.currentTarget.scrollTop + e.currentTarget.offsetHeight) {
e.currentTarget.scrollTop -= 1;
}
});
// Stops preventDefault from being called on document if it sees a scrollable div
$('body').on('touchmove', selScrollable, function(e) {
e.stopPropagation();
});
Note that this won't work if you want to block whole page scrolling when a div does not have overflow. To block that, use the following event handler instead of the one immediately above (adapted from this question):
注意,如果您希望在div没有溢出时阻止整个页面滚动,那么这将不起作用。要阻止它,请使用以下事件处理程序,而不是上面的事件处理程序(根据这个问题改编):
$('body').on('touchmove', selScrollable, function(e) {
// Only block default if internal div contents are large enough to scroll
// Warning: scrollHeight support is not universal. (https://*.com/a/15033226/40352)
if($(this)[0].scrollHeight > $(this).innerHeight()) {
e.stopPropagation();
}
});
#2
23
Using Tyler Dodge's excellent answer kept lagging on my iPad, so I added some throttling code, now it's quite smooth. There is some minimal skipping sometimes while scrolling.
使用泰勒道奇的优秀答案一直滞后于我的iPad,所以我添加了一些节流代码,现在它相当平滑。在滚动时,有时会有一些很小的跳跃。
// Uses document because document will be topmost level in bubbling
$(document).on('touchmove',function(e){
e.preventDefault();
});
var scrolling = false;
// Uses body because jquery on events are called off of the element they are
// added to, so bubbling would not work if we used document instead.
$('body').on('touchstart','.scrollable',function(e) {
// Only execute the below code once at a time
if (!scrolling) {
scrolling = true;
if (e.currentTarget.scrollTop === 0) {
e.currentTarget.scrollTop = 1;
} else if (e.currentTarget.scrollHeight === e.currentTarget.scrollTop + e.currentTarget.offsetHeight) {
e.currentTarget.scrollTop -= 1;
}
scrolling = false;
}
});
// Prevents preventDefault from being called on document if it sees a scrollable div
$('body').on('touchmove','.scrollable',function(e) {
e.stopPropagation();
});
Also, adding the following CSS fixes some rendering glitches (source):
此外,添加以下CSS修复了一些渲染故障(源代码):
.scrollable {
overflow: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
.scrollable * {
-webkit-transform: translate3d(0,0,0);
}
#3
12
First prevent default actions on your entire document as usual:
首先,在整个文档中像往常一样防止默认操作:
$(document).bind('touchmove', function(e){
e.preventDefault();
});
Then stop your class of elements from propagating to the document level. This stops it from reaching the function above and thus e.preventDefault() is not initiated:
然后停止将元素类传播到文档级别。这阻止它到达上面的函数,因此e.preventDefault()没有启动:
$('.scrollable').bind('touchmove', function(e){
e.stopPropagation();
});
This system seems to be more natural and less intensive than calculating the class on all touch moves. Use .on() rather than .bind() for dynamically generated elements.
这个系统似乎比计算所有触控动作的类更自然,也不那么密集。对动态生成的元素使用.on()而不是.bind()。
Also consider these meta tags to prevent unfortunate things from happening while using your scrollable div:
还要考虑这些元标签,以防止在使用可滚动div时发生不幸的事情:
<meta content='True' name='HandheldFriendly' />
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0' name='viewport' />
<meta name="viewport" content="width=device-width" />
#4
7
Can you just add a little more logic into your overscroll disabling code to make sure the targeted element in question is not one that you would like to scroll? Something like this:
您是否可以在您的overscroll禁用代码中添加更多的逻辑,以确保所涉及的目标元素不是您想要滚动的元素?是这样的:
document.body.addEventListener('touchmove',function(e){
if(!$(e.target).hasClass("scrollable")) {
e.preventDefault();
}
});
#5
5
Check if the scrollable element is already scrolled to the top when trying to scroll up or to the bottom when trying to scroll down and then preventing the default action to stop the entire page from moving.
当尝试向上滚动时,检查可滚动元素是否已经滚动到顶部,或者在尝试向下滚动时检查到底部,然后防止默认操作阻止整个页面移动。
var touchStartEvent;
$('.scrollable').on({
touchstart: function(e) {
touchStartEvent = e;
},
touchmove: function(e) {
if ((e.originalEvent.pageY > touchStartEvent.originalEvent.pageY && this.scrollTop == 0) ||
(e.originalEvent.pageY < touchStartEvent.originalEvent.pageY && this.scrollTop + this.offsetHeight >= this.scrollHeight))
e.preventDefault();
}
});
#6
4
I was looking for a way to prevent all body scrolling when there's a popup with a scrollable area (a "shopping cart" popdown that has a scrollable view of your cart).
我正在寻找一种方法来阻止所有的身体滚动,当有一个带有可滚动区域的弹出窗口时(一个“购物车”弹出,它有一个可滚动的购物车视图)。
I wrote a far more elegant solution using minimal javascript to just toggle the class "noscroll" on your body when you have a popup or div that you'd like to scroll (and not "overscroll" the whole page body).
我编写了一个更优雅的解决方案,使用最小的javascript,当您有一个想要滚动的弹出窗口或div时,只需在您的身体上切换类“noscroll”(而不是“overscroll”整个页面体)。
while desktop browsers observe overflow:hidden -- iOS seems to ignore that unless you set the position to fixed... which causes the whole page to be a strange width, so you have to set the position and width manually as well. use this css:
桌面浏览器观察到溢出:隐藏——iOS似乎忽略了这一点,除非你将位置设置为固定……这导致整个页面的宽度很奇怪,所以您还必须手动设置位置和宽度。使用这个css:
.noscroll {
overflow: hidden;
position: fixed;
top: 0;
left: 0;
width: 100%;
}
and this jquery:
这jquery:
/* fade in/out cart popup, add/remove .noscroll from body */
$('a.cart').click(function() {
$('nav > ul.cart').fadeToggle(100, 'linear');
if ($('nav > ul.cart').is(":visible")) {
$('body').toggleClass('noscroll');
} else {
$('body').removeClass('noscroll');
}
});
/* close all popup menus when you click the page... */
$('body').click(function () {
$('nav > ul').fadeOut(100, 'linear');
$('body').removeClass('noscroll');
});
/* ... but prevent clicks in the popup from closing the popup */
$('nav > ul').click(function(event){
event.stopPropagation();
});
#7
3
I've work a little workarround without jquery. Not perfert but works fine (especially if you have a scroll-x in a scoll-y) https://github.com/pinadesign/overscroll/
我在没有jquery的情况下做了一些工作。不是perfert,但是它工作得很好(特别是如果您在scoll-y中有一个scroll-x), https://github.com/pinadesign/overscroll/
Fell free to participate and improve it
*参与并改进它
#8
3
Best solution to this is css/html: Make a div to wrap your elements in, if you dont have it already And set it to position fixed and overflow hidden. Optional, set height and width to 100% if you want it to fill the whole screen and nothing but the whole screen
最好的解决方案是css/html:创建一个div来包装元素,如果你没有的话,将它设置为固定的和溢出的位置。可选,设置高度和宽度为100%,如果你想让它填满整个屏幕,除了整个屏幕什么都没有
#wrapper{
height: 100%;
width: 100%;
position: fixed;
overflow: hidden;
}
<div id="wrapper">
<p>All</p>
<p>Your</p>
<p>Elements</p>
</div>
#9
1
This solution doesn't require you to put a scrollable class on all your scrollable divs so is more general. Scrolling is allowed on all elements which are, or are children of, INPUT elements contenteditables and overflow scroll or autos.
这个解决方案不需要在所有的可滚动divs上放置一个可滚动类,因此更通用。滚动允许对输入元素contenteditables和溢出滚动或autos的子元素进行滚动。
I use a custom selector and I also cache the result of the check in the element to improve performance. No need to check the same element every time. This may have a few issues as only just written but thought I'd share.
我使用一个自定义选择器,并在元素中缓存检查结果,以提高性能。不需要每次都检查相同的元素。这篇文章可能有一些问题,只是刚刚写完,但我想和大家分享一下。
$.expr[':'].scrollable = function(obj) {
var $el = $(obj);
var tagName = $el.prop("tagName");
return (tagName !== 'BODY' && tagName !== 'HTML') && (tagName === 'INPUT' || $el.is("[contentEditable='true']") || $el.css("overflow").match(/auto|scroll/));
};
function preventBodyScroll() {
function isScrollAllowed($target) {
if ($target.data("isScrollAllowed") !== undefined) {
return $target.data("isScrollAllowed");
}
var scrollAllowed = $target.closest(":scrollable").length > 0;
$target.data("isScrollAllowed",scrollAllowed);
return scrollAllowed;
}
$('body').bind('touchmove', function (ev) {
if (!isScrollAllowed($(ev.target))) {
ev.preventDefault();
}
});
}
#10
1
While disabling all "touchmove" events might seem like a good idea, as soon as you need other scrollable elements on the page it will cause problems. On top of that, if you only disable "touchmove" events on certain elements (e.g. body if you want the page to be non-scrollable), as soon as it is enabled anywhere else, IOS will cause unstoppable propagation in Chrome when the URL bar toggles.
虽然禁用所有的“touchmove”事件似乎是一个好主意,但是只要需要页面上的其他可滚动元素,就会导致问题。最重要的是,如果你只在某些元素上禁用“touchmove”事件(例如,如果你希望页面是不可滚动的,则禁用body),一旦在其他地方启用,当URL栏切换时,IOS就会在Chrome中引起不可阻挡的传播。
While I cannot explain this behavior, it looks like the only way to prevent seems to set the body's position to fixed
. The only problem doing is that you will lose the position of the document - this is especially annoying in modals for example. One way to solve it would be to use these simple VanillaJS functions:
虽然我无法解释这种行为,但似乎防止这种行为的唯一方法似乎是将身体的位置固定下来。惟一的问题是您将丢失文档的位置—例如,在modals中尤其令人讨厌。一种解决方法是使用这些简单的VanillaJS函数:
function disableDocumentScrolling() {
if (document.documentElement.style.position != 'fixed') {
// Get the top vertical offset.
var topVerticalOffset = (typeof window.pageYOffset != 'undefined') ?
window.pageYOffset : (document.documentElement.scrollTop ?
document.documentElement.scrollTop : 0);
// Set the document to fixed position (this is the only way around IOS' overscroll "feature").
document.documentElement.style.position = 'fixed';
// Set back the offset position by user negative margin on the fixed document.
document.documentElement.style.marginTop = '-' + topVerticalOffset + 'px';
}
}
function enableDocumentScrolling() {
if (document.documentElement.style.position == 'fixed') {
// Remove the fixed position on the document.
document.documentElement.style.position = null;
// Calculate back the original position of the non-fixed document.
var scrollPosition = -1 * parseFloat(document.documentElement.style.marginTop);
// Remove fixed document negative margin.
document.documentElement.style.marginTop = null;
// Scroll to the original position of the non-fixed document.
window.scrollTo(0, scrollPosition);
}
}
Using this solution you can have a fixed document and any other element in your page can overflow by using simple CSS (e.g., overflow: scroll;
). No need for special classes or anything else.
使用这个解决方案,您可以有一个固定的文档,并且通过使用简单的CSS(例如,overflow: scroll;),页面中的任何其他元素都可以溢出。不需要特殊的课程或其他任何东西。
#11
0
Here's a zepto compatible solution
这是一个兼容zepto的解决方案
if (!$(e.target).hasClass('scrollable') && !$(e.target).closest('.scrollable').length > 0) {
console.log('prevented scroll');
e.preventDefault();
window.scroll(0,0);
return false;
}
#12
0
this one works for me (plain javascript)
这个对我来说是有用的(纯javascript)
var fixScroll = function (className, border) { // className = class of scrollElement(s), border: borderTop + borderBottom, due to offsetHeight
var reg = new RegExp(className,"i"); var off = +border + 1;
function _testClass(e) { var o = e.target; while (!reg.test(o.className)) if (!o || o==document) return false; else o = o.parentNode; return o;}
document.ontouchmove = function(e) { var o = _testClass(e); if (o) { e.stopPropagation(); if (o.scrollTop == 0) { o.scrollTop += 1; e.preventDefault();}}}
document.ontouchstart = function(e) { var o = _testClass(e); if (o && o.scrollHeight >= o.scrollTop + o.offsetHeight - off) o.scrollTop -= off;}
}
fixScroll("fixscroll",2); // assuming I have a 1px border in my DIV
html:
html:
<div class="fixscroll" style="border:1px gray solid">content</div>
#13
0
Try this It'll work perfect.
试试这个,会很管用的。
$('body.overflow-hidden').delegate('#skrollr-body','touchmove',function(e){
e.preventDefault();
console.log('Stop skrollrbody');
}).delegate('.mfp-auto-cursor .mfp-content','touchmove',function(e){
e.stopPropagation();
console.log('Scroll scroll');
});
#14
0
I had surprising luck with with simple:
我很幸运地做到了简单:
body {
height: 100vh;
}
It works great to disable overscroll for pop-ups or menus and it doesn't force browser bars to appear like when using position:fixed. BUT - you need to save scroll position before setting fixed height and restore it when hiding the pop-up, otherwise, browser will scroll to top.
它非常适合禁用弹出窗口或菜单,它不会强迫浏览器栏在使用位置时出现:固定。但是-你需要在设置固定高度之前保存滚动位置,并在隐藏弹出窗口时恢复它,否则浏览器会滚动到顶部。
#1
84
This solves the issue when you scroll past the beginning or end of the div
当您滚动到div的开头或结尾时,这就解决了这个问题
var selScrollable = '.scrollable';
// Uses document because document will be topmost level in bubbling
$(document).on('touchmove',function(e){
e.preventDefault();
});
// Uses body because jQuery on events are called off of the element they are
// added to, so bubbling would not work if we used document instead.
$('body').on('touchstart', selScrollable, function(e) {
if (e.currentTarget.scrollTop === 0) {
e.currentTarget.scrollTop = 1;
} else if (e.currentTarget.scrollHeight === e.currentTarget.scrollTop + e.currentTarget.offsetHeight) {
e.currentTarget.scrollTop -= 1;
}
});
// Stops preventDefault from being called on document if it sees a scrollable div
$('body').on('touchmove', selScrollable, function(e) {
e.stopPropagation();
});
Note that this won't work if you want to block whole page scrolling when a div does not have overflow. To block that, use the following event handler instead of the one immediately above (adapted from this question):
注意,如果您希望在div没有溢出时阻止整个页面滚动,那么这将不起作用。要阻止它,请使用以下事件处理程序,而不是上面的事件处理程序(根据这个问题改编):
$('body').on('touchmove', selScrollable, function(e) {
// Only block default if internal div contents are large enough to scroll
// Warning: scrollHeight support is not universal. (https://*.com/a/15033226/40352)
if($(this)[0].scrollHeight > $(this).innerHeight()) {
e.stopPropagation();
}
});
#2
23
Using Tyler Dodge's excellent answer kept lagging on my iPad, so I added some throttling code, now it's quite smooth. There is some minimal skipping sometimes while scrolling.
使用泰勒道奇的优秀答案一直滞后于我的iPad,所以我添加了一些节流代码,现在它相当平滑。在滚动时,有时会有一些很小的跳跃。
// Uses document because document will be topmost level in bubbling
$(document).on('touchmove',function(e){
e.preventDefault();
});
var scrolling = false;
// Uses body because jquery on events are called off of the element they are
// added to, so bubbling would not work if we used document instead.
$('body').on('touchstart','.scrollable',function(e) {
// Only execute the below code once at a time
if (!scrolling) {
scrolling = true;
if (e.currentTarget.scrollTop === 0) {
e.currentTarget.scrollTop = 1;
} else if (e.currentTarget.scrollHeight === e.currentTarget.scrollTop + e.currentTarget.offsetHeight) {
e.currentTarget.scrollTop -= 1;
}
scrolling = false;
}
});
// Prevents preventDefault from being called on document if it sees a scrollable div
$('body').on('touchmove','.scrollable',function(e) {
e.stopPropagation();
});
Also, adding the following CSS fixes some rendering glitches (source):
此外,添加以下CSS修复了一些渲染故障(源代码):
.scrollable {
overflow: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
.scrollable * {
-webkit-transform: translate3d(0,0,0);
}
#3
12
First prevent default actions on your entire document as usual:
首先,在整个文档中像往常一样防止默认操作:
$(document).bind('touchmove', function(e){
e.preventDefault();
});
Then stop your class of elements from propagating to the document level. This stops it from reaching the function above and thus e.preventDefault() is not initiated:
然后停止将元素类传播到文档级别。这阻止它到达上面的函数,因此e.preventDefault()没有启动:
$('.scrollable').bind('touchmove', function(e){
e.stopPropagation();
});
This system seems to be more natural and less intensive than calculating the class on all touch moves. Use .on() rather than .bind() for dynamically generated elements.
这个系统似乎比计算所有触控动作的类更自然,也不那么密集。对动态生成的元素使用.on()而不是.bind()。
Also consider these meta tags to prevent unfortunate things from happening while using your scrollable div:
还要考虑这些元标签,以防止在使用可滚动div时发生不幸的事情:
<meta content='True' name='HandheldFriendly' />
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0' name='viewport' />
<meta name="viewport" content="width=device-width" />
#4
7
Can you just add a little more logic into your overscroll disabling code to make sure the targeted element in question is not one that you would like to scroll? Something like this:
您是否可以在您的overscroll禁用代码中添加更多的逻辑,以确保所涉及的目标元素不是您想要滚动的元素?是这样的:
document.body.addEventListener('touchmove',function(e){
if(!$(e.target).hasClass("scrollable")) {
e.preventDefault();
}
});
#5
5
Check if the scrollable element is already scrolled to the top when trying to scroll up or to the bottom when trying to scroll down and then preventing the default action to stop the entire page from moving.
当尝试向上滚动时,检查可滚动元素是否已经滚动到顶部,或者在尝试向下滚动时检查到底部,然后防止默认操作阻止整个页面移动。
var touchStartEvent;
$('.scrollable').on({
touchstart: function(e) {
touchStartEvent = e;
},
touchmove: function(e) {
if ((e.originalEvent.pageY > touchStartEvent.originalEvent.pageY && this.scrollTop == 0) ||
(e.originalEvent.pageY < touchStartEvent.originalEvent.pageY && this.scrollTop + this.offsetHeight >= this.scrollHeight))
e.preventDefault();
}
});
#6
4
I was looking for a way to prevent all body scrolling when there's a popup with a scrollable area (a "shopping cart" popdown that has a scrollable view of your cart).
我正在寻找一种方法来阻止所有的身体滚动,当有一个带有可滚动区域的弹出窗口时(一个“购物车”弹出,它有一个可滚动的购物车视图)。
I wrote a far more elegant solution using minimal javascript to just toggle the class "noscroll" on your body when you have a popup or div that you'd like to scroll (and not "overscroll" the whole page body).
我编写了一个更优雅的解决方案,使用最小的javascript,当您有一个想要滚动的弹出窗口或div时,只需在您的身体上切换类“noscroll”(而不是“overscroll”整个页面体)。
while desktop browsers observe overflow:hidden -- iOS seems to ignore that unless you set the position to fixed... which causes the whole page to be a strange width, so you have to set the position and width manually as well. use this css:
桌面浏览器观察到溢出:隐藏——iOS似乎忽略了这一点,除非你将位置设置为固定……这导致整个页面的宽度很奇怪,所以您还必须手动设置位置和宽度。使用这个css:
.noscroll {
overflow: hidden;
position: fixed;
top: 0;
left: 0;
width: 100%;
}
and this jquery:
这jquery:
/* fade in/out cart popup, add/remove .noscroll from body */
$('a.cart').click(function() {
$('nav > ul.cart').fadeToggle(100, 'linear');
if ($('nav > ul.cart').is(":visible")) {
$('body').toggleClass('noscroll');
} else {
$('body').removeClass('noscroll');
}
});
/* close all popup menus when you click the page... */
$('body').click(function () {
$('nav > ul').fadeOut(100, 'linear');
$('body').removeClass('noscroll');
});
/* ... but prevent clicks in the popup from closing the popup */
$('nav > ul').click(function(event){
event.stopPropagation();
});
#7
3
I've work a little workarround without jquery. Not perfert but works fine (especially if you have a scroll-x in a scoll-y) https://github.com/pinadesign/overscroll/
我在没有jquery的情况下做了一些工作。不是perfert,但是它工作得很好(特别是如果您在scoll-y中有一个scroll-x), https://github.com/pinadesign/overscroll/
Fell free to participate and improve it
*参与并改进它
#8
3
Best solution to this is css/html: Make a div to wrap your elements in, if you dont have it already And set it to position fixed and overflow hidden. Optional, set height and width to 100% if you want it to fill the whole screen and nothing but the whole screen
最好的解决方案是css/html:创建一个div来包装元素,如果你没有的话,将它设置为固定的和溢出的位置。可选,设置高度和宽度为100%,如果你想让它填满整个屏幕,除了整个屏幕什么都没有
#wrapper{
height: 100%;
width: 100%;
position: fixed;
overflow: hidden;
}
<div id="wrapper">
<p>All</p>
<p>Your</p>
<p>Elements</p>
</div>
#9
1
This solution doesn't require you to put a scrollable class on all your scrollable divs so is more general. Scrolling is allowed on all elements which are, or are children of, INPUT elements contenteditables and overflow scroll or autos.
这个解决方案不需要在所有的可滚动divs上放置一个可滚动类,因此更通用。滚动允许对输入元素contenteditables和溢出滚动或autos的子元素进行滚动。
I use a custom selector and I also cache the result of the check in the element to improve performance. No need to check the same element every time. This may have a few issues as only just written but thought I'd share.
我使用一个自定义选择器,并在元素中缓存检查结果,以提高性能。不需要每次都检查相同的元素。这篇文章可能有一些问题,只是刚刚写完,但我想和大家分享一下。
$.expr[':'].scrollable = function(obj) {
var $el = $(obj);
var tagName = $el.prop("tagName");
return (tagName !== 'BODY' && tagName !== 'HTML') && (tagName === 'INPUT' || $el.is("[contentEditable='true']") || $el.css("overflow").match(/auto|scroll/));
};
function preventBodyScroll() {
function isScrollAllowed($target) {
if ($target.data("isScrollAllowed") !== undefined) {
return $target.data("isScrollAllowed");
}
var scrollAllowed = $target.closest(":scrollable").length > 0;
$target.data("isScrollAllowed",scrollAllowed);
return scrollAllowed;
}
$('body').bind('touchmove', function (ev) {
if (!isScrollAllowed($(ev.target))) {
ev.preventDefault();
}
});
}
#10
1
While disabling all "touchmove" events might seem like a good idea, as soon as you need other scrollable elements on the page it will cause problems. On top of that, if you only disable "touchmove" events on certain elements (e.g. body if you want the page to be non-scrollable), as soon as it is enabled anywhere else, IOS will cause unstoppable propagation in Chrome when the URL bar toggles.
虽然禁用所有的“touchmove”事件似乎是一个好主意,但是只要需要页面上的其他可滚动元素,就会导致问题。最重要的是,如果你只在某些元素上禁用“touchmove”事件(例如,如果你希望页面是不可滚动的,则禁用body),一旦在其他地方启用,当URL栏切换时,IOS就会在Chrome中引起不可阻挡的传播。
While I cannot explain this behavior, it looks like the only way to prevent seems to set the body's position to fixed
. The only problem doing is that you will lose the position of the document - this is especially annoying in modals for example. One way to solve it would be to use these simple VanillaJS functions:
虽然我无法解释这种行为,但似乎防止这种行为的唯一方法似乎是将身体的位置固定下来。惟一的问题是您将丢失文档的位置—例如,在modals中尤其令人讨厌。一种解决方法是使用这些简单的VanillaJS函数:
function disableDocumentScrolling() {
if (document.documentElement.style.position != 'fixed') {
// Get the top vertical offset.
var topVerticalOffset = (typeof window.pageYOffset != 'undefined') ?
window.pageYOffset : (document.documentElement.scrollTop ?
document.documentElement.scrollTop : 0);
// Set the document to fixed position (this is the only way around IOS' overscroll "feature").
document.documentElement.style.position = 'fixed';
// Set back the offset position by user negative margin on the fixed document.
document.documentElement.style.marginTop = '-' + topVerticalOffset + 'px';
}
}
function enableDocumentScrolling() {
if (document.documentElement.style.position == 'fixed') {
// Remove the fixed position on the document.
document.documentElement.style.position = null;
// Calculate back the original position of the non-fixed document.
var scrollPosition = -1 * parseFloat(document.documentElement.style.marginTop);
// Remove fixed document negative margin.
document.documentElement.style.marginTop = null;
// Scroll to the original position of the non-fixed document.
window.scrollTo(0, scrollPosition);
}
}
Using this solution you can have a fixed document and any other element in your page can overflow by using simple CSS (e.g., overflow: scroll;
). No need for special classes or anything else.
使用这个解决方案,您可以有一个固定的文档,并且通过使用简单的CSS(例如,overflow: scroll;),页面中的任何其他元素都可以溢出。不需要特殊的课程或其他任何东西。
#11
0
Here's a zepto compatible solution
这是一个兼容zepto的解决方案
if (!$(e.target).hasClass('scrollable') && !$(e.target).closest('.scrollable').length > 0) {
console.log('prevented scroll');
e.preventDefault();
window.scroll(0,0);
return false;
}
#12
0
this one works for me (plain javascript)
这个对我来说是有用的(纯javascript)
var fixScroll = function (className, border) { // className = class of scrollElement(s), border: borderTop + borderBottom, due to offsetHeight
var reg = new RegExp(className,"i"); var off = +border + 1;
function _testClass(e) { var o = e.target; while (!reg.test(o.className)) if (!o || o==document) return false; else o = o.parentNode; return o;}
document.ontouchmove = function(e) { var o = _testClass(e); if (o) { e.stopPropagation(); if (o.scrollTop == 0) { o.scrollTop += 1; e.preventDefault();}}}
document.ontouchstart = function(e) { var o = _testClass(e); if (o && o.scrollHeight >= o.scrollTop + o.offsetHeight - off) o.scrollTop -= off;}
}
fixScroll("fixscroll",2); // assuming I have a 1px border in my DIV
html:
html:
<div class="fixscroll" style="border:1px gray solid">content</div>
#13
0
Try this It'll work perfect.
试试这个,会很管用的。
$('body.overflow-hidden').delegate('#skrollr-body','touchmove',function(e){
e.preventDefault();
console.log('Stop skrollrbody');
}).delegate('.mfp-auto-cursor .mfp-content','touchmove',function(e){
e.stopPropagation();
console.log('Scroll scroll');
});
#14
0
I had surprising luck with with simple:
我很幸运地做到了简单:
body {
height: 100vh;
}
It works great to disable overscroll for pop-ups or menus and it doesn't force browser bars to appear like when using position:fixed. BUT - you need to save scroll position before setting fixed height and restore it when hiding the pop-up, otherwise, browser will scroll to top.
它非常适合禁用弹出窗口或菜单,它不会强迫浏览器栏在使用位置时出现:固定。但是-你需要在设置固定高度之前保存滚动位置,并在隐藏弹出窗口时恢复它,否则浏览器会滚动到顶部。