只是禁用滚动而不隐藏它?

2020/10/16 11:41 · javascript ·  · 0评论

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

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

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

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

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

您仍然应该看到右侧的滚动条,但是内容不可滚动。当您关闭叠加层时,只需使用

body { position: static; overflow-y:auto }

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

更新资料

您还可以做些微的改进:如果document.documentElement.scrollTop在打开图层之前通过javascript获得属性,则可以将该值动态分配为topbody元素的属性:通过这种方法,无论您是否在重新放在顶部或您是否已经滚动。

的CSS

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

JS

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

所选解决方案的四个小补充:

  1. 将“ noscroll”应用于html而非正文,以防止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为双滚动条提供了解决方案

包含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();

我是OP

借助fcalderan的回答,我得以形成解决方案。我将解决方案留在这里,因为它可以清楚地说明如何使用它,并增加了非常关键的细节,width: 100%;

我加了这个班

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

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

这对我来说真的很好。

// 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);
});

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

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

您可以使用隐藏实体的滚动条并overflow: hidden同时设置边距,以使内容不会跳转:

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>

我正是针对我自己的灯箱实现执行此操作。到目前为止似乎运转良好。

这就是我们所采用的解决方案。只需在打开叠加层时保存滚动位置,即可在用户尝试滚动页面时随时滚动回到保存的位置,并在关闭叠加层时关闭侦听器。

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

我有一个类似的问题:一个左侧菜单在出现时会阻止滚动。一旦将高度设置为100vh,滚动条就会消失,内容会向右跳动。

因此,如果您不介意保持滚动条处于启用状态(但将窗口设置为全高,这样它实际上就不会在任何位置滚动),那么另一种可能性是设置一个很小的底部边距,这将使滚动条显示:

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

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

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

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

它应该工作

粗略但可行的方法是迫使滚动回到顶部,从而有效地禁用滚动:

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

当您打开灯箱时,升起标志,而在关闭时,请降下标志。

现场测试用例

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

通过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添加到正文:

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

隐藏时,删除类和填充:

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

noscroll样式就是这样:

.noscroll { overflow: hidden; }

请注意,如果您有任何位置固定的元素,则也需要在这些元素上添加填充。

<div id="lightbox"><body>元素内部,因此,当您滚动灯箱时,也会滚动主体。解决方案是不要将<body>元素扩展到100%以上,将长内容放置在另一个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%。

当在html标签或body标签上显示模式/灯箱时,所有基于javascript的模式/灯箱系统都会使用溢出。

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

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

只需用unset替换hidden,就不会看到内容在滚动条移除模式下滑动。

灯箱打开/显示:

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

灯箱关闭/隐藏:

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

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

通过保存滚动位置并在启用滚动功能后将其恢复,将阻止视口跳到顶部。

的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();
});

除去正文滚动时,摆脱内容跳入固定模式的另一种方法是标准化页面宽度:

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

然后,您可以固定位置播放或溢出:打开模态时隐藏身体。但是它将隐藏水平滚动条-通常在响应式网站上不需要它们。

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"
      });
    };
  }
};

我做了这个功能,用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鼠标进入部分,并取消了removeEventListenerjQuery中的鼠标离开事件,但是您可以随意使用它。

您可以使用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>

然后仅将onscroll事件应用于#global

本文地址:http://javascript.askforanswer.com/zhishijinyonggundongerbuyincangta.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!