防止身体滚动,但允许覆盖滚动 [英] Prevent body scrolling but allow overlay scrolling

查看:135
本文介绍了防止身体滚动,但允许覆盖滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在搜索一个lightbox类型的解决方案,允许这个,但还没有找到一个(请,建议,如果你知道任何)。



我想重新创建的行为就像您在 Pinterest 点击图片时看到的行为。重叠式广告可以滚动(,因为整个重叠式广告向上像页面顶部的网页),但重叠广告的主体是固定的。



我试图使用CSS(,即 div 在整个页面和正文的顶部覆盖 overflow:hidden ),但不能防止 div 可滚动。



如何保持正文/页面不滚动,但继续在全屏容器中滚动?

解决方案

理论



查看pinterest网站的当前实施(以后可能会更改),当您打开覆盖时,会出现 noscroll 类应用于 body 元素和 overflow:hidden 因此 body 不再可滚动。



覆盖(即时创建或已经在页面内通过 display:block 可见,它没有区别) position:fixed overflow -y:scroll 顶部右和底部属性设置为 0 :此样式使叠加填充整个视口。



覆盖层中的 div 只是在 position:static ,那么你看到的垂直滚动条与那个元素相关。



当您关闭缩放时,隐藏叠加层(通过 display:none ),然后你也可以通过javascript完全删除它(或只是里面的内容,这取决于你如何注入它)。



步骤你还必须删除 noscroll 类到 body (因此overflow属性返回其初始值) / p>




代码


Codepen示例


(它通过改变覆盖层的 aria-hidden 属性来显示和隐藏它并增加其可访问性)。

标记

(打开按钮)



 < button type =buttonclass =open-overlay> OPEN LAYER< / button> 


 < section class =overlayaria-hidden =true> 
< div>
< h2>您好,我是叠加层< / h2>
...
< button type =buttonclass =close-overlay> CLOSE LAYER< / button>
< / div>
< / section>

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

  var body = document.body,
overlay = document.querySelector('。overlay'),
overlayBtts = document.querySelectorAll('button [class $ =overlay]');

[] .forEach.call(overlayBtts,function(btt){

btt.addEventListener('click',function(){

/ *检测按钮类名* /
var overlayOpen = this.className ==='open-overlay';

/ *切换叠加层上的aria-hidden状态, b $ b no-scroll class on body * /
overlay.setAttribute('aria-hidden',!overlayOpen);
body.classList.toggle('noscroll',overlayOpen);

/ *在某些移动浏览器上,当叠加层以前是
打开和滚动时,如果再次打开它不会
重置其scrollTop属性* /
overlay.scrollTop = 0;

},false);

});






最后,通过应用于 opacity 属性的CSS 转换具有淡入效果。此外,应用 padding-right 可避免在滚动条消失时对底层文本进行回流。


Codepen示例(淡入淡出)


CSS

  .noscroll {overflow: } 

@media(min-device-width:1025px){
/ *不是绝对必要,只是一个实验
这个具体的例子,不必要
在一些浏览器上* /
.noscroll {
padding-right:15px;
}
}

.overlay {
position:fixed;
overflow-y:scroll;
top:0; left:0; top: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;
}


I've been searching for a "lightbox" type solution that allows this but haven't found one yet (please, suggest if you know of any).

The behavior I'm trying to recreate is just like what you'd see at Pinterest when clicking on an image. The overlay is scrollable (as in the whole overlay moves up like a page on top of a page) but the body behind the overlay is fixed.

I attempted to create this with just CSS (i.e. a div overlay on top of the whole page and body with overflow: hidden), but it doesn't prevent div from being scrollable.

How to keep the body/page from scrolling but keep scrolling inside the fullscreen container?

解决方案

Theory

Looking at current implementation of the pinterest site (it might change in the future), when you open the overlay a noscroll class is applied to the body element and overflow: hidden is set, thus body is no longer scrollable.

The overlay (created on-the-fly or already inside the page and made visible via display: block, it makes no difference) has position : fixed and overflow-y: scroll, with top, left, right and bottom properties set to 0: this style makes the overlay fill the whole viewport.

The div inside the overlay is instead just in position: static then the vertical scrollbar you see is related to that element. As a result the content is scrollable but overlay remains fixed.

When you close the zoom you hide the overlay (via display: none) and then you could also entirely remove it via javascript (or just the content inside, it's up to you how to inject it).

As a final step you have to also remove the noscroll class to the body (so the overflow property returns to its initial value)


Code

Codepen Example

(it works by changing the aria-hidden attribute of the overlay in order to show and hide it and to increase its accessibility).

Markup
(open button)

<button type="button" class="open-overlay">OPEN LAYER</button>

(overlay and close button)

<section class="overlay" aria-hidden="true">
  <div>
    <h2>Hello, I'm the overlayer</h2>
    ...   
    <button type="button" class="close-overlay">CLOSE LAYER</button>
  </div>
</section>

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

});


Finally, here's another example in which the overlay opens with a fade-in effect by a CSS transition applied to the opacity property. Also a padding-right is applied to avoid a reflow on the underlying text when the scrollbar disappears.

Codepen Example (fade)

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; top: 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; 
}

这篇关于防止身体滚动,但允许覆盖滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆