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


198

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

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

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


1
是否可以滚动?(灯箱有任何滚动条吗?)
ŠimeVidas

该网站滚动,但我只想在灯箱打开时将其禁用。我只是想知道是否有可能在显示时禁用滚动条。不需要像在灯箱中进行操作或其他任何操作。
Dejan.S 2012年

将Lightbox与滚动条一起使用会出现什么问题?
manny 2012年

1
@Dejan因为我知道如何禁用所有滚动-这将禁用主滚动条,也是一个在灯箱...
森那维达斯

1
请不要将答案重新编辑回这篇文章。以下答案部分用于解答。如果您对问题的答案不同于下面的答案,则可以在答案选择中添加自己的解决方案。
intcreator's

Answers:


172

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

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

2
它弄乱了我的布局,但经过一些修改后还是可以用的。我喜欢这个,我会尝试更多
Dejan.S 2012年

4
稍加修改,这是可行的。我增加了宽度:100%;我没有用解决方案更新我的问题,但您可以使用以下宽度进行修改:100%;?感谢您的建议
Dejan.S 2012年

3
我不知道为什么,但是这对我来说更好: $('body').css('top', -($('body').scrollTop()) + 'px').addClass('noscroll');
PDXIII

4
@whitesiroi,你是对的。我已经更新了小提琴:jsfiddle.net/evpozdniakov/2m8km9wg谢谢!
evpozdniakov

1
对于那些阅读注释以寻求解决方案的人,最后的小提琴提供了一种在禁用和重新启用滚动条的同时保留两种情况下滚动条位置的解决方案。谢谢!
user1063287 '16

78

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

  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为双滚动条提供了解决方案


1
该程序在台式机上测试良好,但在iPhone上创建了一个空白屏幕,直到读者尝试滚动页面为止。阅读器尝试与页面进行交互后,锁定了滚动条,可以看到预期的屏幕。
Michael Khalili

这与iPad上的Fancybox完美搭配,可通过afterLoad()afterClose回调禁用灯箱图像的滚动。对于其他搜索此问题的人可能有用。
Tomanow

在“启用滚动”部分中,您可能希望在调用“禁用滚动”之后删除放置在html元素上的style属性;是不是

3
jQuery标准化了本机DOM scrollTop,因此“禁用滚动”代码的第2行可以表示为$( window ).scrollTop()
巴尼(Barney)2013年

我认为还需要添加另一件事。在OSX中的Chrome上,浏览器可能会“过度滚动”,从而使滚动具有弹性感。使用此代码,如果您位于页面上方或下方的灰色区域,并且将鼠标悬停在禁用滚动的位置上。它将停留在浏览器窗口上方/下方的位置。因此,您需要添加一个检查负滚动值:if (scrollTop < 0) { scrollTop = 0; }。这是禁用gist.github.com/jayd3e/2eefbbc571cd1668544b的完整代码。
JayD3e 2014年

34

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

1
这很适合我,以前的回答让我的网页反弹,这一个不
波格丹托米

很高兴我能帮助,您可能需要检查“touchmove”也为移动设备,欢呼声
CEED

好吧,这几乎对我有用。它可以在Windows(Firefox,Chrome)和Firefox中的MacOS上运行奇迹...但是后来我去了Windows IE和Edge,以及在Chrome和Safari中的MacOS。问题不再是页面从一侧跳到另一侧,而是滚动条从顶部跳到当前位置,或者页面从顶部闪烁。伙计,这是如此如此接近。也许我们仍然可以使它工作。
史蒂文·文蒂米利亚

这对我来说效果很好,谢谢!在重叠菜单也在页面底部的网站上非常理想!
SauriolJf

12

我是OP

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

我加了这个班

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

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


11

这对我来说真的很好。

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

这是所有人中最好的答案
Jafo

7

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

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

4

您可以使用隐藏实体的滚动条并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>

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


1
我实际上最喜欢这种方法。非常简单,效果很好。谢谢!
dericcain

2

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

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


确实可以工作,但是在固定标题的情况下会污染设计,因为滚动条会在其下方移动。
Leon Willens

@LeonWillens我不确定您的意思。如果您担心叠加层显示在固定标题下,则需要将z-indexof 调整.overlay-shown为大于固定标题。(我的代码在具有固定标头的网站上在生产环境中运行,并且可以正常工作。)
0b10011

不,我在说body标签的滚动条。我昨天尝试了您的代码,并且在页面顶部有一个固定的标题。如果我通过body标签处理滚动,则滚动条将位于固定标题下。
Leon Willens

1
@LeonWillens糟糕,看起来我在生产中已将其修复了,却忘记了更新。看起来好像是$("body")我们在用$(window)z-index: -1您可以使用visibility: hidden或类似的方法,而不是将其隐藏在叠加层上。请参阅jsfiddle.net/8p2gfeha进行快速测试,以查看其是否有效。固定的标题不再出现在滚动条的顶部。我最终将尝试将这些更改纳入答案。
0b10011 '19

奇迹般有效!谢谢您:)
Leon Willens

1

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

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

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

难道不能overflow:hidden避免保证金产生任何影响吗?
Koja

0

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

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

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

它应该工作


0

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

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

当您打开灯箱时,升起标记,然后关闭时,请降下标记。

现场测试用例


0

我喜欢坚持“溢出:隐藏”方法,只添加等于滚动条宽度的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; }

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


我用了这个解决方案。它帮助我避免了双滚动条(主体为一个“空白”,覆盖层内容为第二个)。它在OSX上也可以很好地运行,它可能根本不显示滚动条。
Novazembla

0

<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%。


0

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

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

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

只需用未设置的内容替换隐藏的内容,就不会看到内容在滚动条移除模式下滑动。

灯箱打开/显示:

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

灯箱关闭/隐藏:

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

0

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

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

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


0

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

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

-1

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.