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

新手上路,请多包涵

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

我试图重现的行为就像你在 Pinterest 点击图片时看到的一样。叠加层是可滚动的( _因为整个叠加层像页面顶部的页面一样向上移动_)但叠加层 后面 的主体是固定的。

我试图只用 CSS 来创建它( 即 --- 用 div 覆盖在整个页面和正文的 overflow: hidden ),但它不会阻止 div 从可滚动。

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

原文由 PotatoFro 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 523
2 个回答

理论

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

即时创建或已在页面中注入并通过 display: block 可见的覆盖 - 没有区别- 有 position : fixedoverflow-y: scroll top , left , right and bottom properties set to 0 : this style makes the overlay fill the whole viewport (但现在是 2022 年,所以您可以使用 inset: 0 代替)。

覆盖层内的 divposition: static 所以垂直滚动条与该元素相关。这导致可滚动但固定的覆盖。

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

最后一步是删除应用于 bodynoscroll 类(因此 overflow 属性恢复到之前的值)


代码

代码笔示例

(它通过更改覆盖层的 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;
   }
})


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

Codepen 示例(淡入淡出)

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

原文由 Fabrizio Calderan 发布,翻译遵循 CC BY-SA 4.0 许可协议

overscroll-behavior css 属性允许在到达内容的顶部/底部时覆盖浏览器的默认溢出滚动行为。

只需将以下样式添加到叠加层:

 .overlay {
   overscroll-behavior: contain;
   ...
}

代码笔演示

目前适用于 Chrome、Firefox 和 IE( caniuse )

有关详细信息,请查看 谷歌开发人员文章

原文由 Igor Alemasow 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题