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

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

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


当前回答

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

其他回答

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

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

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

现场测试用例。

我用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);
    }
}

我也遇到过类似的问题:左侧菜单出现时,无法滚动。一旦高度设置为100vh,滚动条就会消失,内容会向右抽搐。

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

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

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

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

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

只需替换隐藏的unset不看到内容滑动下的模式删除滚动条。

Lightbox开放/显示:

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

Lightbox隐藏/关闭:

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

如果覆盖层下的页面可以“固定”在顶部,当你打开覆盖层时,你可以设置

.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));

我之所以建议采用这种方式,只是因为您不需要更改任何滚动事件