如何使用 jQuery 以编程方式禁用页面滚动

Posted

技术标签:

【中文标题】如何使用 jQuery 以编程方式禁用页面滚动【英文标题】:How to programmatically disable page scrolling with jQuery 【发布时间】:2011-04-09 01:37:07 【问题描述】:

使用 jQuery,我想禁用正文的滚动:

我的想法是:

    设置body overflow: hidden; 捕获当前scrollTop();/scrollLeft() 绑定到body滚动事件,设置scrollTop/scrollLeft为捕获的值。

有没有更好的办法?


更新:

请在http://jsbin.com/ikuma4/2/edit查看我的示例以及原因

我知道有人会想“他为什么不在面板上使用position: fixed?”。

请不要这样建议,因为我有其他原因。

【问题讨论】:

"有更好的方法吗?" - 除了让浏览器正常运行吗? “戏剧性地”? 也许是程序化的意思?因为它是 'programatically' 的 Firefox ***拼写更正建议 这个线程正在运行\b\ @Sohnee 禁用滚动!== 错误 【参考方案1】:

我发现这样做的唯一方法与您描述的类似:

    获取当前滚动位置(不要忘记水平轴!)。 将溢出设置为隐藏(可能希望保留以前的溢出值)。 使用 scrollTo() 将文档滚动到存储的滚动位置。

然后,当您准备好再次允许滚动时,撤消所有操作。

编辑:我没有理由不能给你代码,因为我费心去挖掘它......

// lock scroll position, but retain settings for later
var scrollPosition = [
  self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
  self.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
];
var html = jQuery('html'); // it would make more sense to apply this to body, but IE7 won't have that
html.data('scroll-position', scrollPosition);
html.data('previous-overflow', html.css('overflow'));
html.css('overflow', 'hidden');
window.scrollTo(scrollPosition[0], scrollPosition[1]);


// un-lock scroll position
var html = jQuery('html');
var scrollPosition = html.data('scroll-position');
html.css('overflow', html.data('previous-overflow'));
window.scrollTo(scrollPosition[0], scrollPosition[1])

【讨论】:

请参阅jsbin.com/ikuma4/2/edit 并向我解释您的更好的任何理由?我是否遗漏了什么(我问是因为与我的示例相比,我看不出您的答案长度有任何原因) 您的方法在 IE7 中不起作用。我也先尝试过。问题是它对滚动事件的反应不够快。它让文档滚动,然后当您的 JS 将滚动位置重置回您想要的位置时将其捕捉回来。 另外,如果 body 溢出了 auto 以外的任何内容,它将被覆盖。我需要保留现有设置,这样也会增加一些开销。 有谁知道为什么简单地用overflow: hidden 设计htmlbody 是不够的?我们最终仍然需要事件处理程序。 这是一个绝妙的答案。要使其在触摸设备上运行,请查看this 答案。【参考方案2】:

这可能会或可能不会满足您的目的,但您可以扩展 jScrollPane 以在其滚动之前触发其他功能。我只是对此进行了一点测试,但我可以确认您可以跳进去并完全阻止滚动。我所做的只是:

下载演示压缩包:http://github.com/vitch/jScrollPane/archives/master 打开“事件”演示 (events.html) 编辑它以使用非缩小脚本源:<script type="text/javascript" src="script/jquery.jscrollpane.js"></script> 在 jquery.jscrollpane.js 中,插入一个“return;”在第 666 行(吉祥的行号!但如果您的版本略有不同,这是positionDragY(destY, animate) 函数的第一行

启动 events.html,您会看到一个正常滚动的框,由于您的编码干预,它不会滚动。

您可以通过这种方式控制整个浏览器的滚动条(参见 fullpage_scroll.html)。

因此,大概下一步是添加对某个其他函数的调用,该函数会触发并执行您的锚定魔法,然后决定是否继续滚动。您还可以调用 API 来设置 scrollTop 和 scrollLeft。

如果您需要更多帮助,请在您所了解的地方发帖!

希望这有帮助。

【讨论】:

【参考方案3】:

你不能把身体高度设置为 100% 并隐藏溢出吗?见http://jsbin.com/ikuma4/13/edit

【讨论】:

$("html").css( height: '100%', overflow: 'hidden' );它很有效,谢谢阿德里安【参考方案4】:

我在这里提出了一个可能有帮助的答案: jQuery simplemodal disable scrolling

它展示了如何在不移动文本的情况下关闭滚动条。关于simplemodal的部分可以忽略。

【讨论】:

【参考方案5】:

您可以使用此代码:

$("body").css("overflow", "hidden");

【讨论】:

您仍然可以使用鼠标中键滚动。 不,这没关系,没有滚动! 如果您使用一些额外的 css,您可以完全禁用滚动,请参阅我的回答了解更多详细信息。【参考方案6】:

您可以使用可滚动的 div 覆盖窗口,以防止滚动页面上的内容。 而且,通过隐藏和显示,您可以锁定/解锁您的滚动条。

做这样的事情:

#scrollLock 
    width: 100%;
    height: 100%;
    position: fixed;
    overflow: scroll;
    opacity: 0;
    display:none


#scrollLock > div 
    height: 99999px;


function scrollLock()
    $('#scrollLock').scrollTop('10000').show();


function scrollUnlock()
    $('#scrollLock').hide();

【讨论】:

请不要使用“u”和“smth”之类的缩写。花点时间正确拼写,以提高可读性。【参考方案7】:

我只是对tfe 的解决方案进行了一些调整。特别是,我添加了一些额外的控件,以确保当滚动条设置为 hidden 时,页面内容不会移动(又名 page shift)。

可以分别定义两个Javascript函数lockScroll()unlockScroll()来锁定和解锁页面滚动。

function lockScroll()
    $html = $('html'); 
    $body = $('body'); 
    var initWidth = $body.outerWidth();
    var initHeight = $body.outerHeight();

    var scrollPosition = [
        self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
        self.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
    ];
    $html.data('scroll-position', scrollPosition);
    $html.data('previous-overflow', $html.css('overflow'));
    $html.css('overflow', 'hidden');
    window.scrollTo(scrollPosition[0], scrollPosition[1]);   

    var marginR = $body.outerWidth()-initWidth;
    var marginB = $body.outerHeight()-initHeight; 
    $body.css('margin-right': marginR,'margin-bottom': marginB);
 

function unlockScroll()
    $html = $('html');
    $body = $('body');
    $html.css('overflow', $html.data('previous-overflow'));
    var scrollPosition = $html.data('scroll-position');
    window.scrollTo(scrollPosition[0], scrollPosition[1]);    

    $body.css('margin-right': 0, 'margin-bottom': 0);

我假设<body> 没有初始边距。

请注意,虽然上述解决方案在大多数实际情况下都有效,但它并不确定,因为它需要对页面进行一些进一步的定制,例如包含position:fixed 的标题。让我们用一个例子来讨论这个特殊情况。假设有

<body>
<div id="header">My fixedheader</div>
<!--- OTHER CONTENT -->
</body>

#headerposition:fixed; padding:0; margin:0; width:100%

然后,应该在函数lockScroll()unlockScroll() 中添加以下内容:

function lockScroll()
    //Omissis   


    $('#header').css('margin-right', marginR);
 

function unlockScroll()
    //Omissis   

    $('#header').css('margin-right', 0);

最后,注意一些可能的边距或填充的初始值。

【讨论】:

你的 javascript 中有错误 $body.css('margin-right': 0, 'margin-bottom', 0);应该是 $body.css('margin-right': 0, 'margin-bottom': 0); 其实只要用marginRightmarginLeft :)【参考方案8】:

对于有居中布局的人(通过margin:0 auto;),这里是position:fixed 解决方案与@tfe 提出的解决方案的混搭。

如果您遇到页面对齐问题(由于滚动条显示/隐藏),请使用此解决方案。

// lock scroll position, but retain settings for later
var scrollPosition = [
    window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
    window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
];
var $html = $('html'); // bow to the demon known as MSIE(v7)
$html.addClass('modal-noscroll');
$html.data('scroll-position', scrollPosition);
$html.data('margin-top', $html.css('margin-top'));
$html.css('margin-top', -1 * scrollPosition[1]);

…结合…

// un-lock scroll position
var $html = $('html').removeClass('modal-noscroll');
var scrollPosition = $html.data('scroll-position');
var marginTop = $html.data('margin-top');
$html.css('margin-top', marginTop);
window.scrollTo(scrollPosition[0], scrollPosition[1])

…最后,.modal-noscroll 的 CSS…

.modal-noscroll

    position: fixed;
    overflow-y: scroll;
    width: 100%;

我敢说这比任何其他解决方案都更合适,但我还没有彻底测试它那个......:P


编辑:请注意,我不知道这会在触摸设备上执行多糟糕(阅读:炸毁)。

【讨论】:

【参考方案9】:

这将完全禁用滚动:

$('html, body').css(
    overflow: 'hidden',
    height: '100%'
);

恢复:

$('html, body').css(
    overflow: 'auto',
    height: 'auto'
);

在 Firefox 和 Chrome 上测试过。

【讨论】:

仍然在 chrome 上使用鼠标中键滚动。 这会丢失当前的滚动位置。 OP 明确提到了捕获滚动位置,所以我认为他需要这样做。无论如何,我需要它,所以这对我来说用处有限 PS 省略 height: 100% 可以有效地将滚动锁定在当前位置而不会跳转 - 至少在最新的 Chrome 上是这样。 这不是正确的答案。滚动位置未被捕获 像魅力一样工作。这只是提醒'html'和'body'同样重要。【参考方案10】:

我编写了一个 jQuery 插件来处理这个问题:$.disablescroll

它可以防止从鼠标滚轮、触摸移动和按键事件中滚动,例如 Page Down

有一个demo here

用法:

$(window).disablescroll();

// To re-enable scrolling:
$(window).disablescroll("undo");

【讨论】:

我尝试使用您的 disablescroll() 插件在听到 mouswheel/scroll 事件时暂时禁用滚动,但它不起作用。你有没有机会知道实现这种效果的方法? @J.B.我可能可以提供帮助,但 cmets 不是最好的地方。加入我的堆栈溢出聊天,我会看看我能做什么:chat.***.com/rooms/55043/disablescroll-usage 很抱歉,这个插件甚至在你的 jsfiddle 中都不起作用。 您可以告诉我它在哪个浏览器/平台上似乎无法运行,来帮助我检查一下?【参考方案11】:

您也可以使用 DOM 来执行此操作。假设你有一个这样调用的函数:

function disable_scroll() 
document.body.style.overflow="hidden";

仅此而已!希望这对所有其他答案有所帮助!

【讨论】:

【参考方案12】:

试试这个

$('#element').on('scroll touchmove mousewheel', function(e)
  e.preventDefault();
  e.stopPropagation();
  return false;
)

【讨论】:

正是我想要的……几乎。无论如何要在箭头键期间禁用它? @Cody - 将此与 css 溢出结合起来:隐藏 @cubbiu 怎么反转? 你可以使用$('#element').off('scroll touchmove mousewheel'); 很好的解决方案。虽然您如何只禁用 body 滚动但允许在具有 overflow: scroll 的其他子元素中滚动?【参考方案13】:

这就是我最终做的:

CoffeeScript:

    $("input").focus ->
        $("html, body").css "overflow-y","hidden"
        $(document).on "scroll.stopped touchmove.stopped mousewheel.stopped", (event) ->
            event.preventDefault()

    $("input").blur ->
        $("html, body").css "overflow-y","auto"
        $(document).off "scroll.stopped touchmove.stopped mousewheel.stopped"

Javascript:

$("input").focus(function() 
 $("html, body").css("overflow-y", "hidden");
 $(document).on("scroll.stopped touchmove.stopped mousewheel.stopped", function(event) 
   return event.preventDefault();
 );
);

$("input").blur(function() 
 $("html, body").css("overflow-y", "auto");
 $(document).off("scroll.stopped touchmove.stopped mousewheel.stopped");
);

【讨论】:

【参考方案14】:

不确定是否有人尝试过我的解决方案。这适用于整个 body/html,但毫无疑问它可以应用于任何触发滚动事件的元素。

只需根据需要设置和取消设置 scrollLock。

var scrollLock = false;
var scrollMem = left: 0, top: 0;

$(window).scroll(function()
    if (scrollLock) 
        window.scrollTo(scrollMem.left, scrollMem.top);
     else 
        scrollMem = 
            left: self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
            top: self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
        ;
    
);

这是JSFiddle的例子

希望这个对某人有所帮助。

【讨论】:

这个可以正常工作,但有一个例外。当滚动被锁定时,我滚动,它有点抽搐,然后才真正锁定滚动......【参考方案15】:

要关闭滚动试试这个:

var current = $(window).scrollTop();
$(window).scroll(function() 
    $(window).scrollTop(current);
);

重置:

$(window).off('scroll');

【讨论】:

@EveryScreamer 不,它会让屏幕像疯了一样摇晃。试图找到解决方法。【参考方案16】:

一个用于禁用滚动的衬里,包括鼠标中键。

$(document).scroll(function ()  $(document).scrollTop(0); );

edit:无论如何都不需要jQuery,下面与vanilla JS中的相同(这意味着没有框架,只有JavaScript):

document.addEventListener('scroll', function ()  this.documentElement.scrollTop = 0; this.body.scrollTop = 0; )

this.documentElement.scrollTop - 标准

this.body.scrollTop - IE 兼容性

【讨论】:

【参考方案17】:

如果您只想禁用键盘导航滚动,您可以覆盖 keydown 事件。

$(document).on('keydown', function(e)
    e.preventDefault();
    e.stopPropagation();
);

【讨论】:

【参考方案18】:

有人贴了这段代码,有恢复时不保留滚动位置的问题。原因是人们倾向于将它应用于 html 和 body 或只是 body 但它应该只应用于 html。这样在恢复滚动位置时将保持:

$('html').css(
    'overflow': 'hidden',
    'height': '100%'
);

恢复:

$('html').css(
    'overflow': 'auto',
    'height': 'auto'
);

【讨论】:

不是'overflow': 'auto', 使用'overflow': 'initial', @evtuhovdo 这就是我所缺少的。谢谢【参考方案19】:

您可以将函数附加到滚动事件并阻止其默认行为。

var $window = $(window);

$window.on("mousewheel DOMMouseScroll", onMouseWheel);

function onMouseWheel(e) 
    e.preventDefault();

https://jsfiddle.net/22cLw9em/

【讨论】:

它有效。只需要发布的重置代码匹配Patricks answer【参考方案20】:

试试这个代码:

    $(function()  
        // ...

        var $body = $(document);
        $body.bind('scroll', function() 
            if ($body.scrollLeft() !== 0) 
                $body.scrollLeft(0);
            
        );

        // ...
    );

【讨论】:

【参考方案21】: 隐藏卷轴:$("body").css("overflow", "hidden"); 恢复卷轴:$("body").css("overflow", "initial");

【讨论】:

【参考方案22】:

我认为最好和干净的解决方案是:

window.addEventListener('scroll',() => 
    var x = window.scrollX;
    var y = window.scrollY;
    window.scrollTo(x,y);
);

使用 jQuery:

$(window).on('scroll',() => 
    var x = window.scrollX;
    var y = window.scrollY;
    window.scrollTo(x,y)
)

那些事件监听器应该阻止滚动。 只需删除它们即可重新启用滚动

【讨论】:

【参考方案23】:

我正在使用以下代码来禁用滚动,它工作正常

    $('html').css(
      'overflow': 'hidden',
      'height': '100%'
    );

除了在我的 android 平板电脑上,url 地址栏和顶部窗口标签仍然可见,当用户上下滚动时,窗口也会上下滚动大约 40px,并显示/隐藏 url 栏和标签。 有没有办法防止这种情况并完全禁用滚动?

【讨论】:

【参考方案24】:

如果想以编程方式禁用滚动,您可以使用:

overflow: clip;

如果您想为用户禁用滚动,您可以使用:

overflow: hidden;

https://developer.mozilla.org/en-US/docs/Web/CSS/overflow

overflow 属性的浏览器支持各不相同:

https://caniuse.com/?search=overflow

【讨论】:

以上是关于如何使用 jQuery 以编程方式禁用页面滚动的主要内容,如果未能解决你的问题,请参考以下文章

是否可以为特定的 jQuery Ajax 调用禁用 Turbolinks 以防止页面刷新和滚动?

Objective-C:如何在 UIScrollView 中禁用垂直滚动

jQuery 数据表。如何以编程方式更改当前页面?

如何使用 Objective-C 以编程方式使我的 UIView 可水平滚动?

以编程方式禁用 UICollectionView 中的垂直滚动

UITextView如何禁用带有内容插入的水平滚动