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

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

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


当前回答

我用scrollLock方法解决了这个问题,该方法为滚动轮事件和按下键事件设置侦听器,并使用preventScroll方法处理这些事件。就像这样:

preventScroll = function (e) {
    // prevent scrollwheel events
    e.preventDefault();
    e.stopPropagation();

    // prevent keydown events
    var keys = [32, 33, 34, 35, 37, 38, 39, 40];
    if (keys.includes(e.keyCode)) {
        e.preventDefault();
    }

    return false;
}

scrollLock = function (lock) {
    if (lock) {
        document.querySelector("#container").addEventListener("wheel", preventScroll);
        document.addEventListener("keydown", preventScroll);
    }
    else {
        document.querySelector("#container").removeEventListener("wheel", preventScroll);
        document.querySelector("#container").removeEventListener("keydown", preventScroll);
    }
}

其他回答

你可以用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事件。

我是OP

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

我添加了这个类

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

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

我有一些其他固定的元素在页面和设置主体的位置固定导致了一堆其他问题,所以我做了一个hack的方式:

const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;

// on opening modal
document.body.style.overflow = "hidden"
document.body.style.paddingRight = `${scrollbarWidth}px`

// on closing modal
document.body.style.overflow = "unset",
document.body.style.paddingRight = "0px"

这个想法是添加一个与浏览器滚动条宽度相同的右填充,以模仿假滚动条并防止内容移动。

你可以保持overflow:隐藏,但手动管理滚动位置:

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

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

应该可以

位置:固定;解决方案有一个缺点-当应用此样式时,页面跳转到顶部。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"
      });
    };
  }
};