我试图禁用父母的html/身体滚动条,而我正在使用一个灯箱。这里的主要词是disable。我不想用溢出来隐藏它。

这样做的原因是overflow: hidden会使站点跳转并占用原来滚动的区域。

我想知道是否有可能禁用滚动条,同时仍然显示它。


当前回答

我喜欢坚持使用“overflow: hidden”方法,只需添加与滚动条宽度相等的右填充。

通过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;
}

当显示覆盖时,在html中添加"noscroll"类,并在body中添加padding-right:

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

当隐藏时,删除类和填充:

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

noscroll样式是这样的:

.noscroll { overflow: hidden; }

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

其他回答

你不能禁用滚动事件,但是你可以禁用导致滚动的相关操作,比如鼠标滚轮和touchmove:

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

位置:固定;解决方案有一个缺点-当应用此样式时,页面跳转到顶部。Angular的材质对话框有一个很好的解决方案,他们通过将定位应用到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"
      });
    };
  }
};

这是我们的解。简单地保存覆盖打开时的滚动位置,在用户试图滚动页面时滚动回保存的位置,并在覆盖关闭时关闭侦听器。

它在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>

我已经做了这个函数,用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);

注意,它是一个高阶函数,所以必须保持对给定实例的引用。

我在鼠标进入中挂钩addEventListener部分,在鼠标离开事件中取消挂钩removeEventListener,但你可以随心所欲地使用它。

我是OP

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

我添加了这个类

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

这对我很有用,我用的是fantyapp。