如何防止滚动? (跨浏览器解决方法)

How to prevent scrolling? (cross-browser workaround)

问题或疑问

我想阻止元素的实际滚动,但我确实想要滚动条的好处(所以有些事情不必以编程方式完成JavaScript 而不是浏览器为我们处理事情)。

有没有人对此有更好或改进的解决方案?非常感谢任何帮助。

2017 年 3 月 13 日更新

我终于想出了一个似乎有效的答案(测试使用)IE11、Edge、Chrome、Firefox、Chrome for Android 和 Firefox for Android.

因此可以忽略此问题或问题描述的其余部分

2017 年 12 月 3 日更新

找到了一种在 IE 11、Edge、Firefox、Chrome 和 Firefox for Android 之间切换(阻止)滚动的方法。虽然它在 Chrome 和 Android 中的效果不是很好(真的很慢)。有人知道为什么吗?

这是我的解决方案 (12-03-2017) 的摘要,但是 Chrome 对于 Android 似乎不喜欢它 (!)。请帮助改进此解决方案(或者可能有与此特定解决方案不同的更好方法?)。

在 IE 11、Edge、Firefox 和 Chrome(工作正常)和 Chrome Android(不喜欢)中测试了以下代码片段,还测试了 Firefox Android(喜欢)。似乎比将两个 div 元素与 position: fixed.

一起使用要好得多

var scrollDisabled = false;

function toggleScroll() {
  scrollDisabled = !scrollDisabled;
}

function doScroll() {
  var st;
  if (!scrollDisabled) {
    $("#scrollsviascrolldistract").css("marginTop", -$(window).scrollTop());
  }
  window.requestAnimationFrame(doScroll);
}

window.requestAnimationFrame(doScroll);

$("#scrolltoggler").on('click', toggleScroll);
body {
  background-color: whitesmoke;
}

#scrollsviascrolldistract {
  position: fixed;
  left: 0px;
  top: 0px;
  width: 100%;
}

#scrolldistract {
  position: absolute;
  left: 0;
  top: 0;
  height: 6000px;
}

.red,
.blue {
  position: relative;
  width: 100%;
  height: 300px;
}

.red {
  background-color: red;
}

.blue {
  background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="scrolldistract">
  <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" height="6000">
</div>

<div id="scrollsviascrolldistract">
  <div class="red">BEGIN</div>
  <div class="blue"><button id="scrolltoggler">Toggle Scroll On/Off</button></div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>

  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">END</div>
</div>

较早的解决方案(请忽略 12-03-2017;请参阅更新的解决方案)

所以我让一个元素滚动但不让它可见。我在里面放了一个间隔图像来填充它到合适的高度。

然后出现跨浏览器问题。

较早的解决方案 - 哪些有效,哪些无效?

Chrome

Chrome 对于 Android

火狐

用于 Android

的火狐

边缘

Internet Explorer 11

代码等

演示在这里: https://jsfiddle.net/hn63z0jt/

一些 HTML5(具有正确的 DOCTYPE):

<div id="scrollsviascrolldistract">
  <div class="red">BEGIN</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>

  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">END</div>
</div>

一些CSS:

body {
  background-color: whitesmoke;
}

#scrollsviascrolldistract {
  position: fixed;
  left: 0px;
  top: 0px;
}

#scrolldistract {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
    overflow-y: scroll;
    background: rgba(0,0,0,0);
  z-index: 999;
}

.red, .blue {
  position: relative;
  width: 900px;
  height: 300px;
}

.red {
  background-color: red;
}

.blue {
  background-color: blue;
}

一些JavaScript(使用jQuery):

$(function() {
    var $window = $(window);
    var $scrollsviascrolldistract = $('#scrollsviascrolldistract');
    var $scrolldistract = $('#scrolldistract');

    $scrolldistract.focus();

    $scrolldistract.on('scroll', function() {
      var scrollTop = $scrolldistract.scrollTop();
      $scrollsviascrolldistract.css('marginTop', -scrollTop);
    });
});

我现在准备好回答我自己的问题了。

所以这是一种切换(防止)滚动的方法:

  • 一个 div 的滚动内容具有 position: fixed(在我的代码中为 #scrollsviascrolldistract)。
  • 一个 div 与滚动内容 div 具有相同的高度,后者具有 position: absolute(或者 position: relative 更可取)。这是嵌入代码示例中的 #scrolldistract
  • 调用 window.requestAnimationFrame 回调函数调整 marginTop 拉取器 div 的值(此处称为 #puller),它应该是滚动内容的第一个子节点div (#scrollsviascrolldistract) 相对于 window 的当前 scrollTop 值(为此使用负边距)。起初我以为我可以拉起滚动内容本身(更改 #scrollsviascrolldistractmarginTop)但这在某些浏览器中不起作用。
  • 然后为了取消控制并防止滚动,可以不更新此 marginTop 值以使滚动内容 div 不受当前滚动条位置的影响。

在 IE 11、Edge、Firefox 和 Chrome 中测试了以下代码片段,还在 Chrome 中测试了 Android,在 Firefox 中测试了 Android。似乎比将两个 div 元素与 position: fixed.

一起使用要好得多

$(function() {
  var scrollDisabled = false;
  var $window = $(window);

  function doScroll() {
    var st = $window.scrollTop();
    if (!scrollDisabled) {
      console.log(st);
      if (st > 6000 - $window.innerHeight()) {
        $("#puller").css("marginTop", -(6000 - $window.innerHeight()));
      } else {
        $("#puller").css("marginTop", -st);
      }
    }
    window.requestAnimationFrame(doScroll);
  }

  window.requestAnimationFrame(doScroll);

  $("#scrolltoggler").on('click', function(e) {
    scrollDisabled = !scrollDisabled;
  });
});
#scrollsviascrolldistract {
  position: fixed;
  left: 0px;
  top: 0px;
  width: 100%;
}

#scrolldistract {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 6000px;
}

#puller {
  position: relative;
  margin-top: 0px;
  left: 0px;
  top: 0px;
}

.red,
.blue {
  position: relative;
  margin-top: auto !important;
  width: 100%;
  height: 300px;
}

.red {
  background-color: red;
}

.blue {
  background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="scrolldistract">
  <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1" height="6000">
</div>


<div id="scrollsviascrolldistract">
  <div id="puller"></div>
  <div class="red">BEGIN</div>
  <div class="blue"><button id="scrolltoggler">Toggle Scroll On/Off</button></div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>

  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">&nbsp;</div>
  <div class="red">&nbsp;</div>
  <div class="blue">END</div>
</div>