css - 防止正文滚动但允许覆盖滚动

标签 css overlay lightbox

我一直在寻找一种允许这样做的“灯箱”类型的解决方案,但还没有找到(如果您知道的话,请提出建议)。

我尝试重新创建的行为与您在 Pinterest 中看到的一样单击图像时。叠加层是可滚动的(因为整个叠加层像页面顶部的页面一样向上移动)但叠加层后面的主体是固定的。

我试图只用 CSS 创建它(div 覆盖在整个页面和主体之上,带有 overflow: hidden) , 但它不会阻止 div 滚动。

如何防止正文/页面滚动但在全屏容器内继续滚动?

最佳答案

理论

查看 pinterest 站点的当前实现(将来可能会更改),当您打开叠加层时,noscroll 类将应用于 body 元素(设置 overflow: hidden) 使 body 不再可滚动。

即时创建或已注入(inject)页面并通过 display: block 显示的叠加层 — 没有区别 — 具有 position :固定overflow-y: scroll, top, left, right and bottom 属性设置为 0:此样式使叠加层填充整个视口(viewport)(但现在我们是 2022 年,因此您可以改用 inset: 0) .

叠加层内的 div 位于 position: static 因此垂直滚动条与该元素相关。这会导致可滚动但固定的覆盖。

当你关闭叠加层时,你必须隐藏它(使用display: none)你甚至可以通过javascript删除节点(或者只是里面的内容,这取决于你但也取决于关于内容的性质)。

最后一步也是删除应用于 bodynoscroll 类(这样 overflow 属性就会恢复到原来的值以前)


代码

Codepen Example

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

标记
(打开按钮)

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

(覆盖和关闭按钮)

<section class="overlay" aria-hidden="true" tabindex="-1">
  <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;
   inset: 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"]'),
    openingBtt;
    
[].forEach.call(overlayBtts, function(btt) {

  btt.addEventListener('click', function() { 
     
     /* Detect the button class name */
     var overlayOpen = this.className === 'open-overlay';
     
     /* storing a reference to the opening button */
     if (overlayOpen) {
        openingBtt = this;
     }
     
     /* 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;
     
      /* forcing focus for Assistive technologies but note:
    - if your modal has just a phrase and a button move the
      focus on the button
    - if your modal has a long text inside (e.g. a privacy
      policy) move the focus on the first heading inside 
      the modal
    - otherwise just focus the modal.

    When you close the overlay restore the focus on the 
    button that opened the modal.
    */
    if (overlayOpen) {
       overlay.focus();
    }
    else {
       openingBtt.focus();
       openingBtt = null;
    }

  }, false);

});

/* detect Escape key when the overlay is open */
document.body.addEventListener('keyup', (ev) => {
   if (ev.key === "Escape" && overlay.getAttribute('aria-hidden') === 'false') {
      overlay.setAttribute('aria-hidden', 'true');
      body.classList.toggle('noscroll', false);
      openingBtt.focus();
      openingBtt = null;
   }
})

最后,这是另一个示例,其中通过应用于 opacity 属性的 CSS transition 以淡入效果打开叠加层。还应用了 padding-right 以避免在滚动条消失时重排底层文本。

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

关于css - 防止正文滚动但允许覆盖滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9280258/

相关文章:

android - 在 Android 上实现 youtube 书签应用

python - Matplotlib 透明叠加 & pdf 透明

android - 在 MapView 上加载 GeoPoints/Path 需要很长时间。有什么办法可以加快速度吗?

html - 为什么这张图片在网上加载时损坏了,但当我预览时却没问题?

javascript - 如何防止 CSS 干扰注入(inject)的 HTML 片段?

html+css双下拉菜单

css - 如果有一个 style.css 和一个 style.min.css 并且我链接到 style.css 浏览器会使用 .min.css 吗?

css - 带有纯 HTML 和 CSS(或最少 JS)的家谱

javascript - 如何在网页上进行paypal嵌入式支付

javascript - 模态对话框 vs 灯箱 - 谁赢了?