我一直在寻找一个“收藏夹”式的解决方案,让这一点,但还没有找到一个还没有(请,建议如果你知道的话)。防止身体滚动,但允许叠加滚动
我试图重新的行为就像在图像上点击时,你会在Pinterest看到的。叠加是可滚动的,但背后覆盖固定身体(在整个覆盖像一个页面在页面的顶部上移)。
我试图只用CSS(即一个div
覆盖在整个页面的顶部和身体overflow: hidden
)创造这一点,但它并不妨碍div
被滚动。
如何保持身体/页面不滚动,但保持在全屏容器内滚动?
我一直在寻找一个“收藏夹”式的解决方案,让这一点,但还没有找到一个还没有(请,建议如果你知道的话)。防止身体滚动,但允许叠加滚动
我试图重新的行为就像在图像上点击时,你会在Pinterest看到的。叠加是可滚动的,但背后覆盖固定身体(在整个覆盖像一个页面在页面的顶部上移)。
我试图只用CSS(即一个div
覆盖在整个页面的顶部和身体overflow: hidden
)创造这一点,但它并不妨碍div
被滚动。
如何保持身体/页面不滚动,但保持在全屏容器内滚动?
理论
纵观目前执行的Pinterest的网站(它可能在未来改变),当您打开一个noscroll
类应用到body
元素,overflow: hidden
设置覆盖,从而body
是不再滚动。
的覆盖(建立在即时或已经在页面内并通过display: block
可见,这都没有区别)有position : fixed
和overflow-y: scroll
,与top
,left
,right
和bottom
属性设置为0
:这种风格品牌覆盖图填充整个视口。
叠加层内的div
只是在position: static
那么您看到的垂直滚动条与该元素有关。因此内容是可滚动的,但覆盖保持不变。
当你关闭缩放时,你会隐藏覆盖图(通过display: none
),然后你也可以通过javascript(或者只是里面的内容,它取决于你如何注入它)完全删除它。
正如你也必须去除noscroll
类的body
最后一步(所以overflow属性回到初始值)
代码
(它通过更改aria-hidden
属性的覆盖,以显示和隐藏它,并增加其可访问性)。
标记
(开门按钮)
<button type="button" class="open-overlay">OPEN LAYER</button>
(覆盖和关闭按钮)
CSS
.noscroll {
overflow: hidden;
}
.overlay {
position: fixed;
overflow-y: scroll;
top: 0; right: 0; bottom: 0; left: 0; }
[aria-hidden="true"] { display: none; }
[aria-hidden="false"] { display: block; }
的Javascript(香草JS)
var body = document.body,
overlay = document.querySelector('.overlay'),
overlayBtts = document.querySelectorAll('button[class$="overlay"]');
[].forEach.call(overlayBtts, function(btt) {
btt.addEventListener('click', function() {
/* Detect the button class name */
var overlayOpen = this.className === 'open-overlay';
/* Toggle the aria-hidden state on the overlay and the
no-scroll class on the body */
overlay.setAttribute('aria-hidden', !overlayOpen);
body.classList.toggle('noscroll', overlayOpen);
/* On some mobile browser when the overlay was previously
opened and scrolled, if you open it again it doesn't
reset its scrollTop property */
overlay.scrollTop = 0;
}, false);
});
最后,这里是另一个例子,其中覆盖与打开淡入效果被应用到opacity
属性CSS transition
。当滚动条消失时,还应用padding-right
以避免底层文本重排。
CSS
.noscroll { overflow: hidden; }
@media (min-device-width: 1025px) {
/* not strictly necessary, just an experiment for
this specific example and couldn't be necessary
at all on some browser */
.noscroll {
padding-right: 15px;
}
}
.overlay {
position: fixed;
overflow-y: scroll;
top: 0; left: 0; right: 0; bottom: 0;
}
[aria-hidden="true"] {
transition: opacity 1s, z-index 0s 1s;
width: 100vw;
z-index: -1;
opacity: 0;
}
[aria-hidden="false"] {
transition: opacity 1s;
width: 100%;
z-index: 1;
opacity: 1;
}
如果你想防止滚动反弹在iOS上,您可以添加位置固定为您.noscroll类
body.noscroll{
position:fixed;
overflow:hidden;
}
一般speakin g,如果你想要一个父(在这种情况下是正文)来防止当一个孩子(在这种情况下是覆盖)滚动时它滚动,那么使该孩子成为父代的兄弟,以防止滚动事件冒泡到家长。在父是身体的情况下,这需要一个额外的包装元素:
<div id="content">
</div>
<div id="overlay">
</div>
见Scroll particular DIV contents with browser's main scrollbar看到它的工作。
最好的解决方案,真正的“开箱即用”的思想,只是不太好措辞。 – 2016-05-04 06:01:22
值得注意的是,有时在body标签中添加“overflow:hidden”并不能完成这项工作。在这些情况下,您也必须将该属性添加到html标记中。
html, body {
overflow: hidden;
}
我想添加到以前的答案,因为我想这样做,当我打开身体位置的一些布局,爆发在即:固定。为了避免这种情况,我不得不身体的高度也设置为100%:
function onMouseOverOverlay(over){
document.getElementsByTagName("body")[0].style.overflowY = (over?"hidden":"scroll");
document.getElementsByTagName("html")[0].style.position = (over?"fixed":"static");
document.getElementsByTagName("html")[0].style.height = (over?"100%":"auto");
}
不要body
使用overflow: hidden;
。它会自动将所有内容滚动到顶部。也不需要JavaScript。使用overflow: auto;
。该解决方案甚至还可以与移动Safari浏览器:
<div class="overlay">
<div class="overlay-content"></div>
</div>
<div class="background-content">
lengthy content here
</div>
.overlay{
position: fixed;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background-color: rgba(0, 0, 0, 0.8);
.overlay-content {
height: 100%;
overflow: scroll;
}
}
.background-content{
height: 100%;
overflow: auto;
}
更新:
对于谁想要键盘空格键,页面上/下工作的人:你需要把重点放在覆盖,例如,点击它,或手动JS专注于这部分内容之前的div
将响应键盘。与覆盖层“关闭”时相同,因为它只是将覆盖层移到侧面。否则,浏览器,这只是两个正常的div
s,它不知道为什么它应该关注其中的任何一个。
使用以下HTML:
<body>
<div class="page">Page content here</div>
<div class="overlay"></div>
</body>
然后JavaScript来拦截和停止滚动:
$(".page").on("touchmove", function(event) {
event.preventDefault()
});
然后让事情恢复正常:
$(".page").off("touchmove");
这是我唯一的解决方案。谢谢。 hvala :) – riogrande 2017-09-01 09:31:42
我发现这个问题试图解决我在Ipad上的页面问题而当我将固定div显示为弹出图像时,Iphone - body正在滚动。
有些答案很好,但是没有一个解决了我的问题。我发现Christoffer Pettersson发表了以下博文。在那里提出的解决方案帮助了iOS设备的问题,它帮助我滚动背景问题。
Six things I learnt about iOS Safari's rubber band scrolling
至于有人建议我包括链接的情况下博客文章的主要观点被过时。
“为了禁用用户可以在”菜单打开“时滚动背景页面,通过应用一些JavaScript和CSS类,可以控制哪些元素应该被允许滚动或不滚动。
基于此Stackoverflow答案,您可以在touchmove事件触发时控制禁用滚动的元素不应该 执行其默认滚动操作。
document.ontouchmove = function (event) {
var isTouchMoveAllowed = true, target = event.target;
while (target !== null) {
if (target.classList && target.classList.contains('disable-scrolling')) {
isTouchMoveAllowed = false;
break;
}
target = target.parentNode;
}
if (!isTouchMoveAllowed) {
event.preventDefault();
}
};
,然后把禁用,滚动类页面的div:
<div class="page disable-scrolling">
对于触摸设备,尝试在重叠的包装增加了1px的宽,101vh
最小高度透明的股利。然后将-webkit-overflow-scrolling:touch; overflow-y: auto;
添加到包装。这诱使移动Safari浏览器认为覆盖层是可滚动的,从而拦截来自身体的触摸事件。
下面是一个示例页面。打开移动Safari浏览器:下面的代码http://www.originalfunction.com/overlay.html
https://gist.github.com/YarGnawh/90e0647f21b5fa78d2f678909673507f
Jup,这个伎俩。只需为每个可滚动容器添加'-webkit-overflow-scrolling:touch;'来拦截触摸事件。 – Mati 2016-09-27 07:37:05
我仍然可以滚动iPhone – 2017-02-24 14:21:31
@SeniorSimoneZandara我不是。这工作正常,以防止背景滚动 – godblessstrawberry 2018-02-27 07:34:57
使用禁用和启用滚动条。
Scroll = (
function(){
var x,y;
function hndlr(){
window.scrollTo(x,y);
//return;
}
return {
disable : function(x1,y1){
x = x1;
y = y1;
if(window.addEventListener){
window.addEventListener("scroll",hndlr);
}
else{
window.attachEvent("onscroll", hndlr);
}
},
enable: function(){
if(window.removeEventListener){
window.removeEventListener("scroll",hndlr);
}
else{
window.detachEvent("onscroll", hndlr);
}
}
}
})();
//for disabled scroll bar.
Scroll.disable(0,document.body.scrollTop);
//for enabled scroll bar.
Scroll.enable();
所选择的答案是正确的,但有一些限制:
<input>
打开虚拟键盘<body>
在模式将直接将所有未来的卷轴<body>
我没有修复的第一个问题,但希望对第二个问题有所了解。令人困惑的是,Bootstrap用于记录键盘问题,但他们声称它已修复,引用http://output.jsbin.com/cacido/quiet作为修复的一个示例。
的确,这个例子在我的测试中可以在iOS上正常工作。但是,将其升级到最新的Bootstrap(v4)将会打破它。
为了弄清楚它们之间的区别是什么,我减少了一个测试用例,不再依赖于Bootstrap,http://codepen.io/WestonThayer/pen/bgZxBG。
决定因素是奇怪的。避免键盘问题似乎需要background-color
不组上包含模态和模态的内容的根<div>
必须嵌套在另一个<div>
,它可以有background-color
集。
为了测试它,取消在Codepen示例以下线:
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
display: none;
overflow: hidden;
-webkit-overflow-scrolling: touch;
/* UNCOMMENT TO BREAK */
/* background-color: white; */
}
如果目的是取消对移动/触摸设备则最直接的方法做到这一点是利用touch-action: none;
。
例子:
const app = document.getElementById('app');
const overlay = document.getElementById('overlay');
let body = '';
for (let index = 0; index < 500; index++) {
body += index + '<br />';
}
app.innerHTML = body;
app.scrollTop = 200;
overlay.innerHTML = body;
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
#app {
background: #f00;
position: absolute;
height: 100%;
width: 100%;
overflow-y: scroll;
line-height: 20px;
}
#overlay {
background: rgba(0,0,0,.5);
position: fixed;
top: 0;
left: 0;
right: 0;
height: 100%;
padding: 0 0 0 100px;
overflow: scroll;
}
<div id='app'></div>
<div id='overlay'></div>
(。这个例子并不在堆栈溢出的情况下工作,你将需要重新创建它在一个单独的页面)
如果您想禁用滚动#app
容器,只需添加touch-action: none;
即可。
如果触摸操作实际上在iOS上工作。在这种情况下,不需要将整个“应用程序”封装在单独的div中。 – powerbuoy 2017-12-05 18:57:35
大多数解决方案都存在这样的问题,即他们不保留滚动位置,所以我查看了Facebook如何执行此操作。除了垫层含量设定为position: fixed
他们还设置了顶部动态地保留滚动位置:
scrollPosition = window.pageYOffset;
mainEl.style.top = -scrollPosition + 'px';
然后,当你再次除去覆盖,你需要重新设置滚动条的位置:
window.scrollTo(0, scrollPosition);
我创建了一个小例子来演示此溶液
let overlayShown = false;
let scrollPosition = 0;
document.querySelector('.toggle').addEventListener('click', function() {
if (overlayShown) {
\t \t showOverlay();
} else {
removeOverlay();
}
overlayShown = !overlayShown;
});
function showOverlay() {
scrollPosition = window.pageYOffset;
\t const mainEl = document.querySelector('.main-content');
mainEl.style.top = -scrollPosition + 'px';
\t document.body.classList.add('show-overlay');
}
function removeOverlay() {
\t \t document.body.classList.remove('show-overlay');
\t window.scrollTo(0, scrollPosition);
const mainEl = document.querySelector('.main-content');
mainEl.style.top = 0;
}
.main-content {
background-image: repeating-linear-gradient(lime, blue 103px);
width: 100%;
height: 200vh;
}
.show-overlay .main-content {
position: fixed;
left: 0;
right: 0;
overflow-y: scroll; /* render disabled scroll bar to keep the same width */
}
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
overflow: auto;
}
.show-overlay .overlay {
display: block;
}
.overlay-content {
margin: 50px;
background-image: repeating-linear-gradient(grey, grey 20px, black 20px, black 40px);
height: 120vh;
}
.toggle {
position: fixed;
top: 5px;
left: 15px;
padding: 10px;
background: red;
}
<main class="main-content"></main>
<div class="overlay">
<div class="overlay-content"></div>
</div>
<button class="toggle">Overlay</button>
在我的情况下,这些解决方案在iPhone(iOS 11.0)上都没有解决。
是工作在我的所有设备的唯一有效的解决方法是这一个 - ios-10-safari-prevent-scrolling-behind-a-fixed-overlay-and-maintain-scroll-position
由于这个问题已经很多年前问,我有一个更新的答案。编码器/程序员并不总是具有与元素相同的设置,这意味着某些答案对某些用户有效,而对其他用户则不适用。
这个答案,如果对于那些谁不能有自己的元素位置:固定 - 移动平台
- 短答案 -
document.body.preventDefault(); 事件 .preventDefault();
- 解释/长的答案 -
有document.body.preventDefault(); event.preventDefault();
之间的差异,这是非常重要的。当你阻止身体时,你明确地阻碍了身体上的滚动位置(这在后场很明显)。
如果您的主要元素需要滚动而身体不应该滚动,则需要检测触摸事件。不提供完整代码,但您也需要检测触摸位置。
document.addEventListener('touchmove', handleTouchMove, false);
function handleTouchMove(evt) {
}
在你的handleTouchMove中,检测上下滑动。
if (yDiff > 0) {
/* UP SWIPE */
}else{
/* DOWN SWIPE */
}
你已经这样做了之后,发现如果需要滚动的元素是它的滚动的完整的顶部或底部。
var ExampleElement= document.getElementById('ExampleElement');
if(ExampleElement.scrollHeight - ExampleElement.scrollTop === 0){
evt.preventDefault();
}else{
document.body.preventDefault();
}
return;
对于本示例,以前列出的代码仅检测用户何时滚动到元素的顶部。当用户向下滑动时,应将此代码插入到检测中。据说这样,当他们到达顶端时,身体根本不会让你滚动身体;因为它一直在滚动ExampleElement,它从来没有滚动过正文。当用户向上滑动时添加极性反向以进行检测时,它也会对其反向执行相同的操作。
我很抱歉,但我不会发布完整的编码示例。
overscroll-behavior
css属性允许在到达内容的顶部/底部时覆盖浏览器的默认溢出滚动行为。
只需添加以下样式叠加:
.overlay {
overscroll-behavior: contain;
...
}
现任职于Chrome和Firefox(caniuse)
有关详情,请google developers article。
我一路走来告诉你,这是最新的Chrome,Mozilla和Opera的工作。有一个美好的时光! – 2018-03-06 19:44:29
不是这只是一个“覆盖”插件像hundrets那里使用固定溢出-y滚动位置? – ggzone 2012-02-14 16:17:07
链接到Pinterest没有帮助,因为它的内容位于登录墙后面。 – jtheletter 2015-06-10 02:54:31
** 2017更新:**即使您登录到Pinterest,您发现OP中描述的叠加效果不再存在 - 而是当您单击某个图像时,您只需导航到一个显示大图的普通页面版本的图像。 – Annabel 2017-11-23 00:48:44