有很多这样的问题,有很多答案,但我找不到不涉及事件、脚本、插件等的令人满意的解决方案。我想直接用 HTML 和 CSS 来解决。我终于找到了一个可行的解决方案,尽管它涉及重组标记以打破事件链。
1.基本问题
应用于模态元素的滚动输入(即:鼠标滚轮)将溢出到祖先元素并沿相同方向滚动它,如果某些这样的元素是可滚动的:
(所有示例均应在桌面分辨率上查看)
https://jsfiddle.net/ybkbg26c/5/
HTML:
<div id="parent">
<div id="modal">
This text is pretty long here. Hope fully, we will get some scroll bars.
</div>
</div>
CSS:
#modal {
position: absolute;
height: 100px;
width: 100px;
top: 20%;
left: 20%;
overflow-y: scroll;
}
#parent {
height: 4000px;
}
2.模态滚动没有父滚动
祖先最终滚动的原因是滚动事件冒泡并且链上的某些元素能够处理它。阻止这种情况的一种方法是确保链上的所有元素都不知道如何处理滚动。在我们的示例中,我们可以重构树以将模式移出父元素。出于晦涩的原因,仅保留父级和模态 DOM 同级是不够的;父元素必须由另一个建立新的堆叠上下文的元素包裹。围绕父级的绝对定位的包装器可以解决问题。
我们得到的结果是,只要 modal 接收到滚动事件,该事件就不会冒泡到“父”元素。
通常应该可以重新设计 DOM 树以支持这种行为,而不会影响最终用户看到的内容。
https://jsfiddle.net/0bqq31Lv/3/
HTML:
<div id="context">
<div id="parent">
</div>
</div>
<div id="modal">
This text is pretty long here. Hope fully, we will get some scroll bars.
</div>
CSS(仅限新):
#context {
position: absolute;
overflow-y: scroll;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
3. 启动时除了模态外,其他地方都不能滚动
上面的解决方案仍然允许父级接收滚动事件,只要它们不被模态窗口拦截(即,如果在光标不在模态窗口上方时由鼠标滚轮触发)。这有时是不可取的,我们可能希望在模式启动时禁止所有背景滚动。为此,我们需要在模态框后面插入一个跨越整个视口的额外堆叠上下文。我们可以通过显示一个绝对定位的叠加层来做到这一点,如果需要,它可以是完全透明的(但不是visibility:hidden
)。
https://jsfiddle.net/0bqq31Lv/2/
HTML:
<div id="context">
<div id="parent">
</div>
</div>
<div id="overlay">
</div>
<div id="modal">
This text is pretty long here. Hope fully, we will get some scroll bars.
</div>
CSS(#2之上的新):
#overlay {
background-color: transparent;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}