【问题标题】:How to disable scroll without hiding it?如何禁用滚动而不隐藏它?
【发布时间】:2012-01-31 20:55:53
【问题描述】:

我正在尝试在使用灯箱时禁用父级的 html/body 滚动条。这里的主要词是禁用。我确实想用overflow: hidden; 隐藏它。

这样做的原因是overflow: hidden 使网站跳转并占据了滚动所在的区域。

我想知道是否可以在显示滚动条的同时禁用它。

【问题讨论】:

  • 应该可以滚动吗? (灯箱有滚动条吗?)
  • 网站滚动,但我只想在灯箱打开时禁用它。我只想知道是否可以在显示滚动条时禁用它。不需要其他东西,比如如何在灯箱或其他任何东西中做到这一点。
  • 使用带有滚动条的灯箱有什么问题?
  • @Dejan 因为我知道如何禁用 all 滚动 - 这会禁用主滚动条,但也会禁用灯箱中的滚动条...
  • 请不要将答案编辑回这篇文章。下面的答案部分是为答案。如果您的问题的答案与下面的答案不同,您可以在答案选择中添加自己的解决方案。

标签: javascript jquery html css


【解决方案1】:

如果overlayer下的页面可以“固定”在顶部,打开overlay时可以设置

body { position: fixed; overflow-y:scroll }

您仍应看到右侧滚动条,但内容不可滚动。当您关闭覆盖时,只需使用

恢复这些属性
body { position: static; overflow-y:auto }

我只是提出这种方式只是因为您不需要更改任何滚动事件

更新

您还可以做些小改进:如果您在层打开之前通过 javascript 获得 document.documentElement.scrollTop 属性,您可以将该值动态分配为 body 元素的 top 属性:使用这种方法,页面将站立取而代之的是,无论您是在顶部还是已经滚动。

CSS

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

JS

$('body').css('top', -(document.documentElement.scrollTop) + 'px')
         .addClass('noscroll');

【讨论】:

  • 它与我的布局相混淆,但经过一些修改它可能会起作用。我喜欢这个,我会尝试更多
  • 稍加修改就可以了。我添加了一个宽度:100%;我用解决方案更新了我的问题,但你可以用宽度修改你的问题:100%;?感谢您的建议
  • 我不知道为什么,但这对我来说效果更好:$('body').css('top', -($('body').scrollTop()) + 'px').addClass('noscroll');
  • @whitesiroi,你是对的。我已经更新了小提琴:jsfiddle.net/evpozdniakov/2m8km9wg 谢谢!
  • 对于那些阅读 cmets 以获得解决方案的人,最后一个小提琴提供了一种解决方案,用于在两种情况下都保留滚动条位置的同时禁用和重新启用滚动条。谢谢!
【解决方案2】:

accepted solution 的四个小补充:

  1. 将“noscroll”应用到 html 而不是 body 以防止 IE 中出现双滚动条
  2. 在添加“noscroll”类之前检查是否真的有滚动条。否则,网站也会被新的非滚动滚动条跳转。
  3. 保留任何可能的 scrollTop 以使整个页面不会回到顶部(如 Fabrizio 的更新,但您需要在添加 'noscroll' 类之前获取该值)
  4. 并非所有浏览器都以与http://help.dottoro.com/ljnvjiow.php 中记录的相同方式处理 scrollTop

似乎适用于大多数浏览器的完整解决方案:

CSS

html.noscroll {
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

禁用滚动

if ($(document).height() > $(window).height()) {
     var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
     $('html').addClass('noscroll').css('top',-scrollTop);         
}

启用滚动

var scrollTop = parseInt($('html').css('top'));
$('html').removeClass('noscroll');
$('html,body').scrollTop(-scrollTop);

感谢 Fabrizio 和 Dejan 让我走上正轨,感谢 Brodingo the solution to the double scroll bar

【讨论】:

  • 这在桌面上测试得很好,但在 iPhone 上它会创建一个空白屏幕,直到读者尝试滚动页面。一旦读者尝试与页面交互,预期的屏幕就会在滚动锁定的情况下变得可见。
  • 这与 iPad 上的 Fancybox 完美配合,可以通过 afterLoad()afterClose 回调禁用灯箱图像的滚动。可能对其他搜索此问题的人有用。
  • 在“启用滚动”部分,您可能希望在调用“禁用滚动”后删除放置在 html 元素上的样式属性;不是吗?
  • jQuery 将原生 DOM 的 scrollTop 标准化,因此“禁用滚动”代码的第 2 行可以表示为 $( window ).scrollTop()
  • 我认为还需要添加另一件事。在 OSX 中的 Chrome 上,浏览器可以“过度滚动”,给滚动带来弹性的感觉。如果您位于页面上方或下方的灰色区域,并且您将鼠标悬停在禁用滚动的位置上,则使用此代码。它将粘在浏览器窗口上方/下方的位置。出于这个原因,您需要添加一个负滚动值检查:if (scrollTop < 0) { scrollTop = 0; }。这是禁用gist.github.com/jayd3e/2eefbbc571cd1668544b的完整代码。
【解决方案3】:

包含 jQuery:


禁用

$.fn.disableScroll = function() {
    window.oldScrollPos = $(window).scrollTop();

    $(window).on('scroll.scrolldisabler',function ( event ) {
       $(window).scrollTop( window.oldScrollPos );
       event.preventDefault();
    });
};

启用

$.fn.enableScroll = function() {
    $(window).off('scroll.scrolldisabler');
};

用法

//disable
$("#selector").disableScroll();
//enable
$("#selector").enableScroll();

【讨论】:

  • 这对我来说是完美的,上一个答案让我的页面跳了,这个没有
  • 很高兴我能帮上忙,您可能还需要检查“touchmove”,对于移动设备,干杯
  • 嗯,这几乎对我有用。它在 Windows(Firefox、Chrome)和 Firefox 中的 MacOS 上创造了奇迹……但后来我去了 Windows IE 和 Edge,以及 Chrome 和 Safari 中的 MacOS。问题不再是页面从一侧跳到另一侧,而是滚动条从顶部跳到当前位置或页面在顶部闪烁。伙计,这是 soso 接近。也许我们仍然可以让它工作。
  • 这对我来说非常有效,谢谢!非常适合在覆盖菜单也位于页面底部的网站上使用!
【解决方案4】:

我是主播

在 fcalderan 的回答的帮助下,我能够形成一个解决方案。我将我的解决方案留在这里,因为它使如何使用它变得清晰,并添加了一个非常重要的细节,width: 100%;

我添加了这个类

body.noscroll
{
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

这对我有用,我正在使用 Fancyapp。

【讨论】:

  • 它对我有用,你的解决方案似乎在这里最干净,
  • 跳转到页面顶部
【解决方案5】:

这对我来说真的很有效......

// disable scrolling
$('body').bind('mousewheel touchmove', lockScroll);

// enable scrolling
$('body').unbind('mousewheel touchmove', lockScroll);


// lock window scrolling
function lockScroll(e) {
    e.preventDefault();
}

只需用决定何时锁定滚动的任何内容来包装这两行代码。

例如

$('button').on('click', function() {
     $('body').bind('mousewheel touchmove', lockScroll);
});

【讨论】:

  • 这会导致 Chrome 87 出现错误:[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312 (ref)
  • 您还可以使用箭头键滚动、向上/向下翻页等。您可以禁用所有箭头键的使用,但这会给我的用例带来其他问题。
【解决方案6】:

您不能禁用滚动事件,但可以禁用导致滚动的相关操作,例如鼠标滚轮和触摸移动:

$('body').on('mousewheel touchmove', function(e) {
      e.preventDefault();
});

【讨论】:

  • 可以用纯javascript做吗?
【解决方案7】:

可以用overflow: hidden隐藏body的滚动条,同时设置一个margin,让内容不跳转:

let marginRightPx = 0;
if(window.getComputedStyle) {
    let bodyStyle = window.getComputedStyle(document.body);
    if(bodyStyle) {
        marginRightPx = parseInt(bodyStyle.marginRight, 10);
    }
}

let scrollbarWidthPx = window.innerWidth - document.body.clientWidth;
Object.assign(document.body.style, {
    overflow: 'hidden',
    marginRight: `${marginRightPx + scrollbarWidthPx}px`
});

然后你可以在页面上添加一个禁用的滚动条来填补空白:

textarea {
  overflow-y: scroll;
  overflow-x: hidden;
  width: 11px;
  outline: none;
  resize: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  border: 0;
}
<textarea></textarea>

我正是为自己的灯箱实现这样做的。到目前为止似乎运行良好。

【讨论】:

  • 我其实最喜欢这种方法。非常简单,效果很好。谢谢!
  • 非常简单,但有一个警告。当浏览器在左侧呈现滚动条 (RTL) 时,这将不起作用。不幸的是,没有简单的方法来检测浏览器将滚动条放在哪里。见stackoverflow.com/q/52404285/2370007
  • 可能是一个边缘问题,但如果开发工具在侧面打开,它会将开发工具的宽度计为滚动条的一部分。
【解决方案8】:

这是我们采用的解决方案。只需在覆盖打开时保存滚动位置,在用户尝试滚动页面时滚动回保存的位置,并在覆盖关闭时关闭监听器。

它在 IE 上有点跳动,但在 Firefox/Chrome 上就像一个魅力。

var body = $("body"),
  overlay = $("#overlay"),
  overlayShown = false,
  overlayScrollListener = null,
  overlaySavedScrollTop = 0,
  overlaySavedScrollLeft = 0;

function showOverlay() {
  overlayShown = true;

  // Show overlay
  overlay.addClass("overlay-shown");

  // Save scroll position
  overlaySavedScrollTop = body.scrollTop();
  overlaySavedScrollLeft = body.scrollLeft();

  // Listen for scroll event
  overlayScrollListener = body.scroll(function() {
    // Scroll back to saved position
    body.scrollTop(overlaySavedScrollTop);
    body.scrollLeft(overlaySavedScrollLeft);
  });
}

function hideOverlay() {
  overlayShown = false;

  // Hide overlay
  overlay.removeClass("overlay-shown");

  // Turn scroll listener off
  if (overlayScrollListener) {
    overlayScrollListener.off();
    overlayScrollListener = null;
  }
}

// Click toggles overlay
$(window).click(function() {
  if (!overlayShown) {
    showOverlay();
  } else {
    hideOverlay();
  }
});
/* Required */
html, body { margin: 0; padding: 0; height: 100%; background: #fff; }
html { overflow: hidden; }
body { overflow-y: scroll; }

/* Just for looks */
.spacer { height: 300%; background: orange; background: linear-gradient(#ff0, #f0f); }
.overlay { position: fixed; top: 20px; bottom: 20px; left: 20px; right: 20px; z-index: -1; background: #fff; box-shadow: 0 0 5px rgba(0, 0, 0, .3); overflow: auto; }
.overlay .spacer { background: linear-gradient(#88f, #0ff); }
.overlay-shown { z-index: 1; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<h1>Top of page</h1>
<p>Click to toggle overlay. (This is only scrollable when overlay is <em>not</em> open.)</p>
<div class="spacer"></div>
<h1>Bottom of page</h1>
<div id="overlay" class="overlay">
  <h1>Top of overlay</h1>
  <p>Click to toggle overlay. (Containing page is no longer scrollable, but this is.)</p>
  <div class="spacer"></div>
  <h1>Bottom of overlay</h1>
</div>

【讨论】:

  • 确实有效,但在固定标题的情况下会污染设计,因为滚动条会潜入它下方。
  • @LeonWillens 我不确定你的意思。如果您担心覆盖出现在固定标题下,则需要将.overlay-shownz-index 调整为大于固定标题。 (我在具有固定标题的站点上在生产环境中运行此代码,它工作正常。)
  • 不,我说的是body 标签的滚动条。我昨天试验了你的代码,我的页面顶部有一个固定的标题。如果我通过body 标签处理滚动,滚动条将位于固定标题下。
  • @LeonWillens 哎呀,看起来我在某个时候在生产中修复了这个问题并忘记更新它。看起来我们使用的是$(window),而不是$("body")。而不是覆盖层上的z-index: -1 来隐藏它,您可以使用visibility: hidden 或类似的。请参阅jsfiddle.net/8p2gfeha 进行快速测试,看看它是否有效。固定标题不再出现在滚动条的顶部。我最终会尝试将这些更改合并到答案中。
  • 像魅力一样工作!谢谢你:)
【解决方案9】:

我喜欢坚持“溢出:隐藏”方法,只添加等于滚动条宽度的 padding-right。

获取滚动条宽度函数,by lostsource

function getScrollbarWidth() {
    var outer = document.createElement("div");
    outer.style.visibility = "hidden";
    outer.style.width = "100px";
    outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps

    document.body.appendChild(outer);

    var widthNoScroll = outer.offsetWidth;
    // force scrollbars
    outer.style.overflow = "scroll";

    // add innerdiv
    var inner = document.createElement("div");
    inner.style.width = "100%";
    outer.appendChild(inner);        

    var widthWithScroll = inner.offsetWidth;

    // remove divs
    outer.parentNode.removeChild(outer);

    return widthNoScroll - widthWithScroll;
}

在显示叠加层时,将“noscroll”类添加到 html 并添加 padding-right 到 body:

$(html).addClass("noscroll");
$(body).css("paddingRight", getScrollbarWidth() + "px");

隐藏时,移除类和填充:

$(html).removeClass("noscroll");
$(body).css("paddingRight", 0);

noscroll 样式就是这样:

.noscroll { overflow: hidden; }

请注意,如果您有任何带有 position:fixed 的元素,您也需要为这些元素添加填充。

【讨论】:

  • 我使用了这个解决方案。它帮助我避免了双滚动条(一个“空白”用于正文,第二个用于覆盖内容)。它在 OSX 上也能很好地工作,可能根本不显示滚动条。
【解决方案10】:

这是working demo。使用纯 JavaScript 可以做到这一点:

const { body, documentElement } = document;
let { scrollTop } = document.documentElement;

function disableScroll() {
  scrollTop = documentElement.scrollTop;
  body.style.top = `-${scrollTop}px`;
  body.classList.add("scroll-disabled");
}

function enableScroll() {
  body.classList.remove("scroll-disabled");
  documentElement.scrollTop = scrollTop;
  body.style.removeProperty("top");
}

这是 CSS:

.scroll-disabled {
  position: fixed;
  width: 100%;
  overflow-y: scroll;
}

我们在body 上使用position: fixed 来防止它被滚动,我们使用overflow-y 来显示滚动条。由于position: fixed 的工作方式,我们还需要设置width

我们跟踪滚动位置并在禁用滚动时更新它,以便我们可以在禁用滚动时使用top 适当地定位body,并在启用滚动时恢复滚动位置。否则body 在禁用或启用滚动时会一直跳到顶部。

启用滚动时,我们会从 body 中删除 top 样式。如果您在 body 上的 positionstatic 不同,这可以防止它破坏您的布局。

如果你在html上使用scroll-behavior: smooth,你还需要像这样修改enableScroll函数:

function enableScroll() {
  body.classList.remove("scroll-disabled");
  // Set "scroll-behavior" to "auto"
  documentElement.style.scrollBehavior = "auto";
  documentElement.scrollTop = scrollTop;
  // Remove "scroll-behavior: auto" after restoring scroll position
  documentElement.style.removeProperty("scroll-behavior");
  body.style.removeProperty("top");
}

我们需要将scroll-behavior临时设置为auto,这样就不会跳转了。

【讨论】:

    【解决方案11】:

    您可以保持溢出:隐藏但手动管理滚动位置:

    在显示实际滚动位置的跟踪之前:

    var scroll = [$(document).scrollTop(),$(document).scrollLeft()];
    //show your lightbox and then reapply scroll position
    $(document).scrollTop(scroll[0]).scrollLeft(scroll[1]);
    

    它应该可以工作

    【讨论】:

      【解决方案12】:

      &lt;div id="lightbox"&gt;&lt;body&gt; 元素内,因此当您滚动灯箱时,您也会滚动正文。解决方案是不要将 &lt;body&gt; 元素扩展超过 100%,将长内容放置在另一个 div 元素中,并在需要时使用 div 向此 div 元素添加滚动条overflow: auto

      html {
        height: 100%
      }
      body {
        margin: 0;
        height: 100%
      }
      #content {
        height: 100%;
        overflow: auto;
      }
      #lightbox {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
      }
      <html>
        <body>
          <div id="content">much content</div>
          <div id="lightbox">lightbox<div>
        </body>
      </html>

      现在,滚动灯箱(以及body)没有任何效果,因为主体不超过屏幕高度的 100%。

      【讨论】:

        【解决方案13】:

        我遇到了类似的问题:左侧菜单在出现时会阻止滚动。将高度设置为 100vh 后,滚动条消失并且内容向右猛拉。

        因此,如果您不介意启用滚动条(但将窗口设置为全高,以便它实际上不会滚动到任何地方),那么另一种可能性是设置一个很小的底部边距,这将保持滚动条显示:

        body {
            height: 100vh;
            overflow: hidden;
            margin: 0 0 1px;
        }
        

        【讨论】:

        • overflow:hidden 不会阻止边距产生任何影响吗?
        【解决方案14】:

        所有基于 modal/lightbox javascript 的系统在 html 标记或 body 标记上显示 modal/lightbox 时都会使用溢出。

        显示灯箱时,js 推送隐藏在 html 或 body 标签上的溢出。 当 lightbox 被隐藏时,一些会删除隐藏的,另一些会在 html 或 body 标记上自动推送溢出。

        在 Mac 上工作的开发者,没有看到滚动条的问题。

        只需将 hidden 替换为 unset 即可在移除滚动条的模态下不看到内容滑动。

        灯箱打开/显示:

        <html style="overflow: unset;"></html>
        

        灯箱关闭/隐藏:

        <html style="overflow: auto;"></html>
        

        【讨论】:

          【解决方案15】:

          如果overlayer下的页面可以“固定”在顶部,打开overlay时可以设置

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

          将此类提供给可滚动的主体,您应该仍然可以看到右侧的滚动条但内容不可滚动。

          要保持页面的位置,请在 jquery 中执行此操作

          $('body').css('top', - ($(window).scrollTop()) + 'px').addClass('disableScroll');
          

          当您关闭叠加层时,只需将这些属性恢复为

          var top = $('body').position().top;
          $('body').removeClass('disableScroll').css('top', 0).scrollTop(Math.abs(top));
          

          我只是提出这种方式只是因为您不需要更改任何滚动事件

          【讨论】:

            【解决方案16】:

            这将通过保存滚动位置并在启用滚动时恢复它来停止视口跳转到顶部。

            CSS

            .no-scroll{
              position: fixed; 
              width:100%;
              min-height:100vh;
              top:0;
              left:0;
              overflow-y:scroll!important;
            }
            

            JS

            var scrollTopPostion = 0;
            
            function scroll_pause(){
              scrollTopPostion = $(window).scrollTop();
              $("body").addClass("no-scroll").css({"top":-1*scrollTopPostion+"px"});
            }
            
            function scroll_resume(){
              $("body").removeClass("no-scroll").removeAttr("style");
              $(window).scrollTop(scrollTopPostion);
            }
            

            现在你需要做的就是调用函数

            $(document).on("click","#DISABLEelementID",function(){
               scroll_pause();
            });
            
            $(document).on("click","#ENABLEelementID",function(){
               scroll_resume();
            });
            

            【讨论】:

              【解决方案17】:

              在移除正文滚动时消除固定模式上的内容跳转的另一种解决方案是标准化页面宽度:

              body {width: 100vw; overflow-x: hidden;}
              

              然后您可以在模态打开时使用固定位置或溢出:隐藏为身体。但它会隐藏水平滚动条——响应式网站通常不需要它们。

              【讨论】:

                【解决方案18】:

                position: fixed; 解决方案有一个缺点 - 应用此样式时页面会跳转到顶部。 Angular 的 Material Dialog 有一个很好的解决方案,他们通过将定位应用于 html 元素来伪造滚动位置。

                以下是我修改后的仅用于垂直滚动的算法。左滚动阻塞以完全相同的方式完成。

                // This class applies the following styles:
                // position: fixed;
                // overflow-y: scroll;
                // width: 100%;
                const NO_SCROLL_CLASS = "bp-no-scroll";
                
                const coerceCssPixelValue = value => {
                  if (value == null) {
                    return "";
                  }
                
                  return typeof value === "string" ? value : `${value}px`;
                };
                
                export const blockScroll = () => {
                  const html = document.documentElement;
                  const documentRect = html.getBoundingClientRect();
                  const { body } = document;
                
                  // Cache the current scroll position to be restored later.
                  const cachedScrollPosition =
                    -documentRect.top || body.scrollTop || window.scrollY || document.scrollTop || 0;
                
                  // Cache the current inline `top` value in case the user has set it.
                  const cachedHTMLTop = html.style.top || "";
                
                  // Using `html` instead of `body`, because `body` may have a user agent margin,
                  // whereas `html` is guaranteed not to have one.
                  html.style.top = coerceCssPixelValue(-cachedScrollPosition);
                
                  // Set the magic class.
                  html.classList.add(NO_SCROLL_CLASS);
                
                  // Return a function to remove the scroll block.
                  return () => {
                    const htmlStyle = html.style;
                    const bodyStyle = body.style;
                
                    // We will need to seamlessly restore the original scroll position using
                    // `window.scroll`. To do that we will change the scroll behavior to `auto`.
                    // Here we cache the current scroll behavior to restore it later.
                    const previousHtmlScrollBehavior = htmlStyle.scrollBehavior || "";
                    const previousBodyScrollBehavior = bodyStyle.scrollBehavior || "";
                
                    // Restore the original inline `top` value.
                    htmlStyle.top = cachedHTMLTop;
                
                    // Remove the magic class.
                    html.classList.remove(NO_SCROLL_CLASS);
                
                    // Disable user-defined smooth scrolling temporarily while we restore the scroll position.
                    htmlStyle.scrollBehavior = bodyStyle.scrollBehavior = "auto";
                
                    // Restore the original scroll position.
                    window.scroll({
                      top: cachedScrollPosition.top
                    });
                
                    // Restore the original scroll behavior.
                    htmlStyle.scrollBehavior = previousHtmlScrollBehavior;
                    bodyStyle.scrollBehavior = previousBodyScrollBehavior;
                  };
                };
                

                逻辑非常简单,如果您不关心某些极端情况,可以进一步简化。例如,这是我使用的:

                export const blockScroll = () => {
                  const html = document.documentElement;
                  const documentRect = html.getBoundingClientRect();
                  const { body } = document;
                  const screenHeight = window.innerHeight;
                
                  // Only do the magic if document is scrollable
                  if (documentRect.height > screenHeight) {
                    const cachedScrollPosition =
                      -documentRect.top || body.scrollTop || window.scrollY || document.scrollTop || 0;
                
                    html.style.top = coerceCssPixelValue(-cachedScrollPosition);
                
                    html.classList.add(NO_SCROLL_CLASS);
                
                    return () => {
                      html.classList.remove(NO_SCROLL_CLASS);
                
                      window.scroll({
                        top: cachedScrollPosition,
                        behavior: "auto"
                      });
                    };
                  }
                };
                

                【讨论】:

                  【解决方案19】:

                  我做了一个函数,用 JS 解决了这个问题。 这个原则可以很容易地扩展和定制,这对我来说是一个很大的优点。

                  使用这个js DOM API函数:

                  const handleWheelScroll = (element) => (event) => {
                    if (!element) {
                      throw Error("Element for scroll was not found");
                    }
                    const { deltaY } = event;
                    const { clientHeight, scrollTop, scrollHeight } = element;
                    if (deltaY < 0) {
                      if (-deltaY > scrollTop) {
                        element.scrollBy({
                          top: -scrollTop,
                          behavior: "smooth",
                        });
                        event.stopPropagation();
                        event.preventDefault();
                      }
                      return;
                    }
                  
                    if (deltaY > scrollHeight - clientHeight - scrollTop) {
                      element.scrollBy({
                        top: scrollHeight - clientHeight - scrollTop,
                        behavior: "smooth",
                      });
                      event.stopPropagation();
                      event.preventDefault();
                      return;
                    }
                  };
                  

                  简而言之,如果滚动将滚动给定元素(您要滚动的元素)之外的其他内容,此函数将停止事件传播和默认行为。

                  然后你可以像这样连接和解开它:

                  const wheelEventHandler = handleWheelScroll(elementToScrollIn);
                  
                  window.addEventListener("wheel", wheelEventHandler, {
                      passive: false,
                  });
                  
                  window.removeEventListener("wheel", wheelEventHandler);
                  

                  注意它是一个高阶函数,因此您必须保留对给定实例的引用。

                  我在 jQuery 中将鼠标输入中的 addEventListener 部分和鼠标离开事件中的 removeEventListener 挂钩,但您可以随意使用它。

                  【讨论】:

                    【解决方案20】:

                    我注意到 YouTube 网站正是这样做的。所以通过稍微检查一下,我已经能够确定他们正在使用@polymer/iron-overlay-behavior,幸运的是,它可以在 Web 组件/Polymer 之外相当隐蔽地使用:

                    import {
                        pushScrollLock,
                        removeScrollLock,
                    } from '@polymer/iron-overlay-behavior/iron-scroll-manager';
                    
                    // lock scroll everywhere except scrollElement
                    pushScrollLock(scrollElement);
                    
                    // restore scrolling
                    removeScrollLock(scrollElement);
                    
                    • 允许在选定元素中滚动
                    • 不会以任何方式影响样式
                    • 在 YouTube 网站上经过实战考验

                    这似乎是一个成熟的解决方案,而且肯定是我能找到的最好的解决方案。这个包有点重,但我猜当只导入iron-scroll-manager 时,它的大部分都变得不捆绑了。

                    干杯

                    【讨论】:

                      【解决方案21】:

                      粗鲁但可行的方法是强制滚动回到顶部,从而有效地禁用滚动:

                      var _stopScroll = false;
                      window.onload = function(event) {
                          document.onscroll = function(ev) {
                              if (_stopScroll) {
                                  document.body.scrollTop = "0px";
                              }
                          }
                      };
                      

                      打开灯箱时升旗,关闭灯箱时降旗。

                      Live test case.

                      【讨论】:

                        【解决方案22】:

                        你可以用 Javascript 做到这一点:

                        // Classic JS
                        window.onscroll = function(ev) {
                          ev.preventDefault();
                        }
                        
                        // jQuery
                        $(window).scroll(function(ev) {
                          ev.preventDefault();
                        }
                        

                        然后在您的灯箱关闭时禁用它。

                        但如果您的灯箱包含滚动条,您将无法在它打开时滚动。这是因为window 包含body#lightbox。 所以你必须使用像下面这样的架构:

                        <body>
                          <div id="global"></div>
                          <div id="lightbox"></div>
                        </body>
                        

                        然后仅在#global 上应用onscroll 事件。

                        【讨论】:

                          猜你喜欢
                          • 2014-11-11
                          • 1970-01-01
                          • 2014-04-23
                          • 2011-12-14
                          • 1970-01-01
                          • 1970-01-01
                          • 2011-07-22
                          • 2011-03-20
                          • 2020-01-22
                          相关资源
                          最近更新 更多