如何防止滚动? (跨浏览器解决方法)
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 似乎不喜欢它 (!)。请帮助改进此解决方案(或者可能有与此特定解决方案不同的更好方法?)。
- 一个
div
具有 position: fixed
的滚动内容(在我的代码中为 #scrollsviascrolldistract
)。
- 一个
div
与滚动内容 div
具有相同的高度,后者具有 position: absolute
(或者 position: relative
更可取)。这是嵌入代码示例中的 #scrolldistract
。
- 使用回调函数调用
window.requestAnimationFrame
,调整滚动内容 div
(#scrollsviascrolldistract
) 相对于当前 scrollTop
值的 marginTop
值window 的(为此使用负边距)。
- 然后为了取消控制并防止滚动,可以不更新此
marginTop
值以使滚动内容 div
不受当前滚动条位置的影响。
在 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"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue">END</div>
</div>
较早的解决方案(请忽略 12-03-2017;请参阅更新的解决方案)
所以我让一个元素滚动但不让它可见。我在里面放了一个间隔图像来填充它到合适的高度。
然后出现跨浏览器问题。
较早的解决方案 - 哪些有效,哪些无效?
Chrome
- 可以通过鼠标或滚动条滚动。
- 即使是 focus() 也能正常工作,因此可以立即使用按键进行滚动。
Chrome 对于 Android
- 通过触摸滚动(应该如此)。
火狐
- Ctrl+PageUp/Ctrl+PageDown 切换选项卡并禁用滚动,直到您抓住滚动条。
- 可以通过按键滚动,但必须单击背景区域才能获得焦点。
用于 Android
的火狐
- 彻底的灾难:滚动了一下后停止滚动。不知道为什么。
边缘
- 除了 focus() 之外,似乎可以正常工作。需要单击文档中的某处(red/blue 块或背景)。
Internet Explorer 11
- 只能通过鼠标工作。无法获取焦点,甚至无法手动使用按键滚动。
代码等
演示在这里:
https://jsfiddle.net/hn63z0jt/
一些 HTML5(具有正确的 DOCTYPE):
<div id="scrollsviascrolldistract">
<div class="red">BEGIN</div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </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
值(为此使用负边距)。起初我以为我可以拉起滚动内容本身(更改 #scrollsviascrolldistract
的 marginTop
)但这在某些浏览器中不起作用。
- 然后为了取消控制并防止滚动,可以不更新此
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"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue">END</div>
</div>
问题或疑问
我想阻止元素的实际滚动,但我确实想要滚动条的好处(所以有些事情不必以编程方式完成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 似乎不喜欢它 (!)。请帮助改进此解决方案(或者可能有与此特定解决方案不同的更好方法?)。
- 一个
div
具有position: fixed
的滚动内容(在我的代码中为#scrollsviascrolldistract
)。 - 一个
div
与滚动内容div
具有相同的高度,后者具有position: absolute
(或者position: relative
更可取)。这是嵌入代码示例中的#scrolldistract
。 - 使用回调函数调用
window.requestAnimationFrame
,调整滚动内容div
(#scrollsviascrolldistract
) 相对于当前scrollTop
值的marginTop
值window 的(为此使用负边距)。 - 然后为了取消控制并防止滚动,可以不更新此
marginTop
值以使滚动内容div
不受当前滚动条位置的影响。
在 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"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue">END</div>
</div>
较早的解决方案(请忽略 12-03-2017;请参阅更新的解决方案)
所以我让一个元素滚动但不让它可见。我在里面放了一个间隔图像来填充它到合适的高度。
然后出现跨浏览器问题。
较早的解决方案 - 哪些有效,哪些无效?
Chrome
- 可以通过鼠标或滚动条滚动。
- 即使是 focus() 也能正常工作,因此可以立即使用按键进行滚动。
Chrome 对于 Android
- 通过触摸滚动(应该如此)。
火狐
- Ctrl+PageUp/Ctrl+PageDown 切换选项卡并禁用滚动,直到您抓住滚动条。
- 可以通过按键滚动,但必须单击背景区域才能获得焦点。
用于 Android
的火狐- 彻底的灾难:滚动了一下后停止滚动。不知道为什么。
边缘
- 除了 focus() 之外,似乎可以正常工作。需要单击文档中的某处(red/blue 块或背景)。
Internet Explorer 11
- 只能通过鼠标工作。无法获取焦点,甚至无法手动使用按键滚动。
代码等
演示在这里: https://jsfiddle.net/hn63z0jt/
一些 HTML5(具有正确的 DOCTYPE):
<div id="scrollsviascrolldistract">
<div class="red">BEGIN</div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </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
值(为此使用负边距)。起初我以为我可以拉起滚动内容本身(更改#scrollsviascrolldistract
的marginTop
)但这在某些浏览器中不起作用。 - 然后为了取消控制并防止滚动,可以不更新此
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"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue">END</div>
</div>