ChatGPT解决这个技术问题 Extra ChatGPT

如何暂时禁用滚动?

我正在使用 scrollTo jQuery 插件,想知道是否可以通过 Javascript 暂时禁用窗口元素上的滚动?我想禁用滚动的原因是,当您在 scrollTo 动画时滚动时,它会变得非常难看;)

当然,我可以做一个$("body").css("overflow", "hidden");,然后在动画停止时将其恢复为自动,但如果滚动条仍然可见但不活动会更好。

如果它仍然显示,那么用户被训练认为它必须在运行。如果剂量没有移动或没有响应,那么它将破坏用户对您的页面如何工作的心理模型并导致混乱。我只想找到一种更好的方法来处理动画时的滚动,例如停止动画。
另一种解决方案:stackoverflow.com/questions/9280258/…

g
gblazex

scroll 事件无法取消。但是您可以通过取消这些交互事件来做到这一点:
鼠标 & 触摸滚动与滚动相关的按钮

[工作演示]

// left: 37, up: 38, right: 39, down: 40,
// spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
var keys = {37: 1, 38: 1, 39: 1, 40: 1};

function preventDefault(e) {
  e.preventDefault();
}

function preventDefaultForScrollKeys(e) {
  if (keys[e.keyCode]) {
    preventDefault(e);
    return false;
  }
}

// modern Chrome requires { passive: false } when adding event
var supportsPassive = false;
try {
  window.addEventListener("test", null, Object.defineProperty({}, 'passive', {
    get: function () { supportsPassive = true; } 
  }));
} catch(e) {}

var wheelOpt = supportsPassive ? { passive: false } : false;
var wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';

// call this to Disable
function disableScroll() {
  window.addEventListener('DOMMouseScroll', preventDefault, false); // older FF
  window.addEventListener(wheelEvent, preventDefault, wheelOpt); // modern desktop
  window.addEventListener('touchmove', preventDefault, wheelOpt); // mobile
  window.addEventListener('keydown', preventDefaultForScrollKeys, false);
}

// call this to Enable
function enableScroll() {
  window.removeEventListener('DOMMouseScroll', preventDefault, false);
  window.removeEventListener(wheelEvent, preventDefault, wheelOpt); 
  window.removeEventListener('touchmove', preventDefault, wheelOpt);
  window.removeEventListener('keydown', preventDefaultForScrollKeys, false);
}

更新:修复了带有被动监听器的 Chrome 桌面和现代移动浏览器


给陷入此陷阱的其他开发人员的提示:请确保从其他 jQuery 尝试停止滚动时删除任何和所有“e.stopPropagation()”调用,因为它不仅不起作用,还可以防止事件冒泡到此代码确实有效。希望我浪费的 30 分钟将有助于节省其他人的时间 :)
您可以将 32(空格)添加到禁用的键数组(显示在代码注释中)。
我可以像往常一样滚动它:使用中键按下并移动鼠标......因此这个技巧不会影响像我这样的用户;)
滚动条未被禁用。
我仍然可以通过将文件拖到页面的顶部/底部来使其滚动。这也可以通过选择页面上的文本并在顶部/底部进行相同的拖动来实现。
M
MusikAnimal

只需向主体添加一个类即可:

.stop-scrolling {
  height: 100%;
  overflow: hidden;
}

当你想重新启用滚动时,添加类然后删除,在 IE、FF、Safari 和 Chrome 中测试。

$('body').addClass('stop-scrolling')

对于移动设备,您需要处理 touchmove 事件:

$('body').bind('touchmove', function(e){e.preventDefault()})

并取消绑定以重新启用滚动。在 iOS6 和 Android 2.3.3 中测试

$('body').unbind('touchmove')

知道了!您必须像处理 $('body').bind('touchmove', function(e){e.preventDefault()}) 一样处理 touchmove 事件。编辑此答案以包含此移动解决方案。
很酷,只需要确保任何内部滚动都可以在触摸设备的模式下工作。可以在模态下方进行覆盖并防止覆盖而不是正文上的默认触摸移动。
尽管此解决方案确实有效,但它具有(可能)滚动回页面顶部的不良影响。
这对我不起作用,除非我的选择器是 $('body,html')
此解决方案有效,但当您将此类应用于主体时(例如),滚动条消失并创建“凹凸”效果(在窗口操作系统下)
s
sdleihssirhc

这是一个非常基本的方法:

window.onscroll = function () { window.scrollTo(0, 0); };

在 IE6 中有点跳动。


并不是真正的禁用,更像是尝试滚动时的默认设置。
@Marcus 与不可取消的活动一样好。
即使它并没有真正禁用它,它也会模拟它,这对我来说已经足够了。
恕我直言 - 最佳答案在这里。另外,您不必将其锁定到 (0, 0),只需使用当前滚动位置即可。
但是我们如何重新启用它呢?
M
Mohammad Anini

以下解决方案是基本但纯 JavaScript(无 jQuery):

function disableScrolling(){
    var x=window.scrollX;
    var y=window.scrollY;
    window.onscroll=function(){window.scrollTo(x, y);};
}

function enableScrolling(){
    window.onscroll=function(){};
}

在 Safari 7.1 和 IE 11 中跳跃。最新的 Chrome、Firefox、Opera ok。
在最新的 Chrome 上仍然有点紧张
工作正常,在 safari、chrome 中,但在 IE 中闪烁
如果此解决方案不适用于某些浏览器,那就是浏览器问题
可以设置 window.onscroll=null 而不是添加一个空的匿名函数,nullwindow.onload 的初始值
C
Community

此解决方案将在禁用滚动时保持当前滚动位置,这与将用户跳回顶部的某些解决方案不同。

它基于 galambalazs' answer,但支持触摸设备,并使用 jquery 插件包装器重构为单个对象。

Demo here.

On github here.

/**
 * $.disablescroll
 * Author: Josh Harrison - aloof.co
 *
 * Disables scroll events from mousewheels, touchmoves and keypresses.
 * Use while jQuery is animating the scroll position for a guaranteed super-smooth ride!
 */

;(function($) {

    "use strict";

    var instance, proto;

    function UserScrollDisabler($container, options) {
        // spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
        // left: 37, up: 38, right: 39, down: 40
        this.opts = $.extend({
            handleKeys : true,
            scrollEventKeys : [32, 33, 34, 35, 36, 37, 38, 39, 40]
        }, options);

        this.$container = $container;
        this.$document = $(document);
        this.lockToScrollPos = [0, 0];

        this.disable();
    }

    proto = UserScrollDisabler.prototype;

    proto.disable = function() {
        var t = this;

        t.lockToScrollPos = [
            t.$container.scrollLeft(),
            t.$container.scrollTop()
        ];

        t.$container.on(
            "mousewheel.disablescroll DOMMouseScroll.disablescroll touchmove.disablescroll",
            t._handleWheel
        );

        t.$container.on("scroll.disablescroll", function() {
            t._handleScrollbar.call(t);
        });

        if(t.opts.handleKeys) {
            t.$document.on("keydown.disablescroll", function(event) {
                t._handleKeydown.call(t, event);
            });
        }
    };

    proto.undo = function() {
        var t = this;
        t.$container.off(".disablescroll");
        if(t.opts.handleKeys) {
            t.$document.off(".disablescroll");
        }
    };

    proto._handleWheel = function(event) {
        event.preventDefault();
    };

    proto._handleScrollbar = function() {
        this.$container.scrollLeft(this.lockToScrollPos[0]);
        this.$container.scrollTop(this.lockToScrollPos[1]);
    };

    proto._handleKeydown = function(event) {
        for (var i = 0; i < this.opts.scrollEventKeys.length; i++) {
            if (event.keyCode === this.opts.scrollEventKeys[i]) {
                event.preventDefault();
                return;
            }
        }
    };


    // Plugin wrapper for object
    $.fn.disablescroll = function(method) {

        // If calling for the first time, instantiate the object and save
        // reference. The plugin can therefore only be instantiated once per
        // page. You can pass options object in through the method parameter.
        if( ! instance && (typeof method === "object" || ! method)) {
            instance = new UserScrollDisabler(this, method);
        }

        // Instance already created, and a method is being explicitly called,
        // e.g. .disablescroll('undo');
        else if(instance && instance[method]) {
            instance[method].call(instance);
        }

    };

    // Global access
    window.UserScrollDisabler = UserScrollDisabler;

})(jQuery);

很高兴它有用。请注意,我使用 link to this in jQuery plugin format 进行了编辑。
如果禁用滚动按钮确实有效,可能会有所帮助
@user1672694,它在 Chrome 中工作。你的浏览器是什么,你在哪个演示页面上发现了这个错误?控制台中有任何 JS 错误吗?
在 Chrome(38,Windows 7)上,我仍然可以通过单击并按住中间按钮然后拖动来滚动。
请忽略,我发现绑定它mousewheel很有魅力
u
u01jmg3

很抱歉回答旧帖子,但我正在寻找解决方案并遇到了这个问题。

有许多解决方法可以解决此问题以仍然显示滚动条,例如为容器提供 100% 的高度和 overflow-y: scroll 样式。

在我的例子中,我刚刚创建了一个带有滚动条的 div,我在将 overflow: hidden 添加到正文时显示该滚动条:

function disableScroll() {
    document.getElementById('scrollbar').style.display = 'block';
    document.body.style.overflow = 'hidden';
}

元素滚动条必须具有以下样式:

overflow-y: scroll; top: 0; right: 0; display: none; height: 100%; position: fixed;

这显示了一个灰色滚动条,希望它对未来的访问者有所帮助。


V
Văn Quyết
var winX = null;
var winY = null;

window.addEventListener('scroll', function () {
    if (winX !== null && winY !== null) {
        window.scrollTo(winX, winY);
    }
});

function disableWindowScroll() {
    winX = window.scrollX;
    winY = window.scrollY;
}

function enableWindowScroll() {
    winX = null;
    winY = null;
}

这是这里最好的解决方案。
@jfunk 同意,简洁明了,代码小,完美。谢谢
为了类型安全,我建议使用负数而不是 null
R
Rajat Gupta

我一直在寻找解决此问题的方法,但对上述任何解决方案都不满意(在撰写此答案时),所以我想出了这个解决方案。

CSS

.scrollDisabled {   
    position: fixed;
    margin-top: 0;// override by JS to use acc to curr $(window).scrollTop()
    width: 100%;
}

JS

var y_offsetWhenScrollDisabled=0;

function disableScrollOnBody(){
    y_offsetWhenScrollDisabled= $(window).scrollTop();
    $('body').addClass('scrollDisabled').css('margin-top', -y_offsetWhenScrollDisabled);
}
function enableScrollOnBody(){
    $('body').removeClass('scrollDisabled').css('margin-top', 0);
    $(window).scrollTop(y_offsetWhenScrollDisabled);
}

如果我将 overflow-y: scroll 添加到 .scrollDisabled 样式,我发现这对我有用。否则,每次滚动条隐藏时都会有一点跳跃。当然,这只对我有用,因为我的页面足够长,即使在最大的显示器上也需要滚动条。
H
Hokascha

从 Chrome 56 和其他现代浏览器开始,您必须将 passive:false 添加到 addEventListener 调用才能使 preventDefault 工作。所以我用它来停止在移动设备上滚动:

function preventDefault(e){
    e.preventDefault();
}

function disableScroll(){
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll(){
    document.body.removeEventListener('touchmove', preventDefault, { passive: false });
}

c
centurian

不,我不会使用事件处理,因为:

并非所有事件都能保证到达身体,

选择文本并向下移动实际上会滚动文档,

如果在事件分离阶段出现问题,你注定要失败。

我已经通过使用隐藏的 textarea 进行复制粘贴操作来解决这个问题,猜猜看,每当我进行复制时,页面都会滚动,因为在内部我必须在调用 document.execCommand('copy') 之前选择 textarea。

无论如何,这就是我要走的路,请注意 setTimeout()

document.body.setAttribute('style','overflow:hidden;');
// do your thing...
setTimeout(function(){document.body.setAttribute('style','overflow:visible;');}, 500);

当滚动条瞬间消失时,存在一种闪烁的势头,但这是可以接受的。


我刚刚在表格主体(TBODY)上进行了垂直滚动。停止:this.table.body.style.overflowY = 'hidden';重新启动:this.table.body.style.overflowY = 'auto'
j
jvalen

根据 galambalazs 的帖子,我将添加对触摸设备的支持,允许我们触摸但不能向上或向下滚动:

function disable_scroll() {
   ...
   document.ontouchmove = function(e){ 
        e.preventDefault(); 
   }
}

function enable_scroll() {
   ...
   document.ontouchmove = function(e){ 
     return true; 
   }
}

您确定这是一个答案而不仅仅是其他答案的评论吗?
a
axelra82

根据您希望使用已移除的滚动条实现的目标,您可以只修复要从中移除滚动条的元素(单击时,或您想要暂时停用滚动条的任何其他触发器)

我正在寻找“临时无滚动”解决方案,并且为了我的需要,这解决了

上课

.fixed{
    position: fixed;
}

然后用 Jquery

var someTrigger = $('#trigger'); //a trigger button
var contentContainer = $('#content'); //element I want to temporarily remove scroll from

contentContainer.addClass('notfixed'); //make sure that the element has the "notfixed" class

//Something to trigger the fixed positioning. In this case we chose a button.
someTrigger.on('click', function(){

    if(contentContainer.hasClass('notfixed')){
        contentContainer.removeClass('notfixed').addClass('fixed');

    }else if(contentContainer.hasClass('fixed')){
        contentContainer.removeClass('fixed').addClass('notfixed');
    };
});

我发现这是一个足够简单的解决方案,适用于所有浏览器,也便于在便携式设备(即 iPhone、平板电脑等)上使用。由于元素是临时固定的,所以没有滚动:)

笔记!根据“contentContainer”元素的位置,您可能需要从左侧调整它。当固定类处于活动状态时,可以通过向该元素添加 css left 值来轻松完成

contentContainer.css({
    'left': $(window).width() - contentContainer.width()/2 //This would result in a value that is the windows entire width minus the element we want to "center" divided by two (since it's only pushed from one side)
});

Z
Zolfaghari

我正在使用 showModalDialog,将辅助页面显示为模式对话框。

隐藏主窗口滚动条:

document.body.style.overflow = "hidden";

并在关闭模式对话框时,显示主窗口滚动条:

document.body.style.overflow = "scroll";

从对话框访问主窗口中的元素:

parent.document.getElementById('dialog-close').click();

仅适用于搜索 showModalDialog 的任何人:(在原始代码第 29 行之后)

document.getElementById('dialog-body').contentWindow.dialogArguments = arg;
document.body.style.overflow = "hidden";//****
document.getElementById('dialog-close').addEventListener('click', function(e) {
    e.preventDefault();
    document.body.style.overflow = "scroll";//****
    dialog.close();
});

这在 React 中对我有用,其中 jQuery 不存在并且 React 无权管理 body 标签的状态。
u
u01jmg3

另一种解决方案:

body {
    overflow-y: scroll;
    width: 100%;
    margin: 0 auto;
}

这样你总是有一个垂直滚动条,但由于我的大部分内容都比视口长,这对我来说没问题。内容以一个单独的 div 为中心,但如果没有在正文中再次设置边距,我的内容将保持在左侧。

这是我用来显示弹出窗口/模式的两个函数:

var popup_bodyTop = 0;
var popup_bodyLeft = 0;

function popupShow(id)
{
    $('#'+ id).effect('fade');
    $('#popup-overlay').effect('fade');

    // remember current scroll-position
    // because when setting/unsetting position: fixed to body
    // the body would scroll to 0,0
    popup_bodyLeft = $(document).scrollLeft();
    popup_bodyTop  = $(document).scrollTop();

    // invert position
    var x = - popup_bodyLeft;
    var y = - popup_bodyTop;

    $('body').css('position', 'fixed');
    $('body').css('top', y.toString() +'px');
    $('body').css('left', x.toString() +'px');
}

function popupHide(id)
{
    $('#'+ id).effect('fade');
    $('#popup-overlay').effect('fade');
    $('body').css('position', '');
    $('html, body').scrollTop(popup_bodyTop);
    $('html, body').scrollLeft(popup_bodyLeft);
}

结果:由于左侧滚动条,背景不可滚动且内容无法重新定位。使用当前的 FF、Chrome 和 IE 10 测试。


这对我有用,并且在使用 position:fixed 后滚动到顶部的问题。感谢你!
A
Architect

这是迄今为止我得到的最简单的解决方案。相信我,我尝试了所有其他方法,这是最简单的。它在 Windows 设备上运行良好,从右侧推动页面为系统滚动条留出空间,而 IOS 设备在浏览器中不需要空间用于滚动条。因此,通过使用它,您不需要在右侧添加填充,这样当您使用 css 隐藏 body 或 html 的溢出时页面不会闪烁。

如果您考虑一下,解决方案非常简单。这个想法是在打开弹出窗口的那一刻给 window.scrollTop() 相同的确切位置。当窗口调整大小时也更改该位置(因为一旦发生滚动位置就会更改)。

所以我们开始...

首先让我们创建一个变量,让您知道弹出窗口已打开,并将其命名为 stopWindowScroll。如果我们不这样做,那么您将在页面上收到未定义变量的错误并将其设置为 0 - 未激活。

$(document).ready(function(){
    stopWindowScroll = 0;
});

现在让打开的弹出函数可以是代码中的任何函数,它可以触发您作为插件或自定义使用的任何弹出窗口。在这种情况下,它将是一个简单的自定义弹出窗口,带有一个简单的单击功能文档。

$(document).on('click','.open-popup', function(){
    // Saving the scroll position once opening the popup.
    stopWindowScrollPosition = $(window).scrollTop();
    // Setting the stopWindowScroll to 1 to know the popup is open.
    stopWindowScroll = 1;
    // Displaying your popup.
    $('.your-popup').fadeIn(300);
});

所以接下来我们要做的是创建关闭弹出功能,我再重复一遍,它可以是您已经创建或正在插件中使用的任何功能。重要的是我们需要这 2 个函数将 stopWindowScroll 变量设置为 1 或 0 以了解它何时打开或关闭。

$(document).on('click','.open-popup', function(){
    // Setting the stopWindowScroll to 0 to know the popup is closed.
    stopWindowScroll = 0;
    // Hiding your popup
    $('.your-popup').fadeOut(300);
});

然后让我们创建 window.scroll 函数,这样我们就可以在上面提到的 stopWindowScroll 设置为 1 时阻止滚动 - 激活。

$(window).scroll(function(){
    if(stopWindowScroll == 1) {
         // Giving the window scrollTop() function the position on which
         // the popup was opened, this way it will stay in its place.
         $(window).scrollTop(stopWindowScrollPosition);
    }
});

而已。除了您自己的页面样式外,无需任何 CSS 即可工作。这对我来说就像一个魅力,我希望它可以帮助你和其他人。

这是一个关于 JSFiddle 的工作示例:

JS Fiddle Example

让我知道这是否有帮助。问候。


G
Giulia

你可以这样做:

通过这种方式,您可以节省“微不足道”的内存,并且带有 Position: fixed 的元素不会移动,因此不会影响您的设计本身。

CSS(使用 CSS 让你的生活和记忆更轻松)

html[DisableScroll] {
    overflow-y: scroll;
}

html[DisableScroll] body {
    overflow-y: hidden;
    height: 100vh;
}

JS

var enableScroll = function () {
   document.documentElement
     .removeAttribute('DisableScroll');
}

例如

//当你想启用 escroll 时只需调用这个函数; var enableScroll = function () { document.documentElement .removeAttribute('DisableScroll'); } setTimeout(() => { enableScroll(); }, 2000); *{ 边距:0px;填充:0px } body{ 高度:4000px;背景:#141417 } html[DisableScroll] { overflow-y: scroll } html[DisableScroll] body { overflow-y: hidden;高度:100vh; } body>p{ 颜色:#FBFBFD } div{ 位置:固定;左:0;右:0;边距:自动;宽度:270px;背景:#FBFBFD;颜色:#141417; text-align: center } Document

@@ @@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


< p>@@@@


@@@@


@@@@


@@@@

p>

@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@ @@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


< p>@@@@


@@@@


@@@@


@@@@

p>

@@@@


@@@@


@@@@


@@@@


@@@@


@@@@

< br>

@@@@


@@@@


@@@@


@@@ @


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@ @@@


@@@@


@@@@


@@@@

< br>

@@@@


@@@@


@@@@


@@@ @


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@< /p>

@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@ @@@


@@@@


@@@@


@@@@

< br>

@@@@


@@@@


@@@@


@@@ @


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@< /p>

@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@@@@


@ @@@


@@@@

@@@@


@@@@


@@@@


@@@ @



D
Dan

这个怎么样? (如果您使用的是 jQuery)

var $window = $(window);
var $body = $(window.document.body);

window.onscroll = function() {
    var overlay = $body.children(".ui-widget-overlay").first();

    // Check if the overlay is visible and restore the previous scroll state
    if (overlay.is(":visible")) {
        var scrollPos = $body.data("scroll-pos") || { x: 0, y: 0 };
        window.scrollTo(scrollPos.x, scrollPos.y);
    }
    else {
        // Just store the scroll state
        $body.data("scroll-pos", { x: $window.scrollLeft(), y: $window.scrollTop() });
    }
};

有点跳跃,但这适用于 IE 7(客户端使用它)。其他解决方案没有。
u
u01jmg3

在我看来,取消已接受答案中的事件是一种可怕的方法:/

相反,我在下面使用了 position: fixed; top: -scrollTop();

演示:https://jsfiddle.net/w9w9hthy/5/

从我的 jQuery 弹出项目:https://github.com/seahorsepip/jPopup

//Freeze page content scrolling
function freeze() {
    if($("html").css("position") != "fixed") {
        var top = $("html").scrollTop() ? $("html").scrollTop() : $("body").scrollTop();
        if(window.innerWidth > $("html").width()) {
            $("html").css("overflow-y", "scroll");
        }
        $("html").css({"width": "100%", "height": "100%", "position": "fixed", "top": -top});
    }
}

//Unfreeze page content scrolling
function unfreeze() {
    if($("html").css("position") == "fixed") {
        $("html").css("position", "static");
        $("html, body").scrollTop(-parseInt($("html").css("top")));
        $("html").css({"position": "", "width": "", "height": "", "top": "", "overflow-y": ""});
    }
}

此代码考虑了宽度、高度、滚动条和页面跳转问题。

上述代码解决的可能问题:

宽度,当设置位置固定时,html元素宽度可以小于100%

高度,同上

滚动条,当设置位置固定时,页面内容不再有滚动条,即使它在导致水平页面跳转之前有滚动条也是如此

pagejump,当设置位置固定时页面scrollTop不再有效导致垂直页面跳转

如果有人对以上页面冻结/解冻代码有任何改进,请告诉我,以便我可以将这些改进添加到我的项目中。


D
Daan

最简单的方法是:

$("body").css("overflow", "hidden"); // Remove the scroll bar temporarily

要撤消它:

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

易于实现,但唯一的缺点是:

如果页面居中对齐(水平),页面将向左跳转一点。

这是因为滚动条被移除了,并且视口变得更宽了。


这将重置滚动位置
@AngelDavidCalderaroPacciott 不,滚动位置将保持相同的高度/距离。
@Daan 它确实重置了 Chrome 上的滚动位置
@Tom我刚刚检查过它,它只在某些情况下(当身高与其孩子不相关时)。请尝试将 body 改为 html
我敢打赌您没有在 Iphone 中检查您的解决方案,因为 overflow:hidden 在那里不起作用
S
Stephen Rauch

这是我停止滚动的解决方案(没有 jQuery)。当侧面菜单出现时,我用它来禁用滚动。

我放了 17px 的 padding-right 来补偿滚动条的消失。但这也是有问题的,主要是针对移动浏览器。通过根据 this 获取条形宽度来解决。

All together in this Pen.


M
Milad

为了防止跳跃,这是我使用的

export function toggleBodyScroll(disable) {
  if (!window.tempScrollTop) {
    window.tempScrollTop = window.pageYOffset; 
    // save the current position in a global variable so I can access again later

  }
  if (disable) {
    document.body.classList.add('disable-scroll');
    document.body.style.top = `-${window.tempScrollTop}px`;
  } else {
    document.body.classList.remove('disable-scroll');
    document.body.style.top = `0px`;
    window.scrollTo({top: window.tempScrollTop});
    window.tempScrollTop = 0;
  }
}

在我的 CSS 中

.disable-scroll {
  height: 100%;
  overflow: hidden;
  width: 100%;
  position: fixed;
}


c
cotneit

此答案提出了一种解决方案,用于消除在应用 this solution 中建议的 overflow: hidden 时发生的“碰撞”。由于编辑被拒绝,这里是:

消除应用 overflow: hidden 时发生的“凹凸”,您可以计算滚动条的宽度并将其替换为边距。以下是 body 元素的示例:

const bodyScrollControls = {
  scrollBarWidth: window.innerWidth - document.body.clientWidth,

  disable() {
    document.body.style.marginRight = `${this.scrollBarWidth}px`;
    document.body.style.overflowY = 'hidden';
  },
  enable() {
    document.body.style.marginRight = null;
    document.body.style.overflowY = null;
  },
};

如果一个元素已经有 margin-right,那么获取现有元素并为其添加滚动条宽度应该不是问题。


这是迄今为止最简单的解决方案。谢谢你。你拯救了我的一天:D
Q
Quibble

基于夏安福布斯的回答,以及我通过 fcalderan 在这里找到的回答:Just disable scroll not hide it? 并修复了 Hallodom 的滚动条消失问题

CSS:

.preventscroll{
    position: fixed;
    overflow-y:scroll;
}

JS:

whatever.onclick = function(){
    $('body').addClass('preventscroll');
}
whatevertoclose.onclick = function(){
    $('body').removeClass('preventscroll');
}

此代码确实会将您跳转到页面顶部,但我认为 fcalderan 的代码有一个解决方法。


k
kyun

我知道这是一个老问题,但我不得不做一些非常相似的事情,经过一段时间寻找答案并尝试不同的方法后,我最终使用了一个非常简单的解决方案。

我的问题非常相似,几乎相同,唯一的区别是我不必实际显示滚动条 - 我只需要确保它的宽度仍然可以使用,因此在显示我的叠加层时页面的宽度不会改变.

当我开始将叠加层滑入屏幕时,我会:

$('body').addClass('stop-scrolling').css('margin-right', 8);

在我将叠加层滑出屏幕后,我会这样做:

$('body').removeClass('stop-scrolling').css('margin-right', 0);

重要提示:这非常有效,因为我的叠加层位于 absoluteright: 0pxvisible


R
Robert

我有同样的问题,下面是我的处理方式。

/* file.js */
var body = document.getElementsByTagName('body')[0];
//if window dont scroll
body.classList.add("no-scroll");
//if window scroll
body.classList.remove("no-scroll");

/* file.css */
.no-scroll{
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

希望这有帮助。


P
PerrierCitror

此代码将适用于 Chrome 56 及更多版本(原始答案不再适用于 Chrome)。

使用 DomUtils.enableScroll() 启用滚动。

使用 DomUtils.disableScroll() 禁用滚动。

class DomUtils {
  // left: 37, up: 38, right: 39, down: 40,
  // spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
  static keys = { 37: 1, 38: 1, 39: 1, 40: 1 };

  static preventDefault(e) {
    e = e || window.event;
    if (e.preventDefault) e.preventDefault();
    e.returnValue = false;
  }

  static preventDefaultForScrollKeys(e) {
    if (DomUtils.keys[e.keyCode]) {
      DomUtils.preventDefault(e);
      return false;
    }
  }

  static disableScroll() {
    document.addEventListener('wheel', DomUtils.preventDefault, {
      passive: false,
    }); // Disable scrolling in Chrome
    document.addEventListener('keydown', DomUtils.preventDefaultForScrollKeys, {
      passive: false,
    });
  }

  static enableScroll() {
    document.removeEventListener('wheel', DomUtils.preventDefault, {
      passive: false,
    }); // Enable scrolling in Chrome
    document.removeEventListener(
      'keydown',
      DomUtils.preventDefaultForScrollKeys,
      {
        passive: false,
      }
    ); // Enable scrolling in Chrome
  }
}

m
modex98

我在这里使用这个简单的技巧:

.no-scroll{
  overflow: hidden;
}

let toggle_scrolling_state = () => {
   element.classList.toggle("no-scroll");
}

然后在您想停止滚动事件时调用该函数或...


G
Gurpreet

我在触摸设备上有类似的问题。向元素添加“touch-action:none”解决了这个问题。

了解更多信息。看一下这个:-

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


K
Kareem

将滚动长度存储在全局变量中,并在需要时恢复它!

var sctollTop_length = 0;

function scroll_pause(){
  sctollTop_length = $(window).scrollTop();
  $("body").css("overflow", "hidden");
}

function scroll_resume(){
  $("body").css("overflow", "auto");
  $(window).scrollTop(sctollTop_length);
}

p
pennstump

我在另一个 site 上找到了这个答案:

禁用滚动:

$( ".popup").live({
    popupbeforeposition: function(event, ui) {
    $("body").on("touchmove", false);
}
});

关闭弹出释放滚动后:

$( ".popup" ).live({
    popupafterclose: function(event, ui) {
    $("body").unbind("touchmove");
}
});

这似乎只是停止触摸滚动,但鼠标滚动、箭头键、上下翻页键等仍然有效。 -1
这些“事件”用于触摸滚动,只需替换您需要的任何事件。
此外,这似乎用于其他一些非常具体的情况。位置前弹出?那应该是为了什么?这与暂时禁用滚动有什么关系?至少让它与这种情况相关。看起来你是直接从网站上复制的。