在嵌套的 flexbox 内滚动
我正在开发一个 React 应用程序,该应用程序有一个模式,其中包含一些偶尔需要滚动的选项卡式内容.但是,问题是我无法获得正确的滚动内容.
I'm working on a React app that has a modal with some Tabbed content inside that occasionally needs to scroll. However, the problem is that I can't manage to get the proper content to scroll.
模态分为三个主要部分:
The modal is broken into 3 main sections:
- 页眉
- 应该始终在模态框的顶部可见
- 应该填充 Header 和 Footer 之间的空间,但绝不要从视图中强制任何一个
- Should fill space between Header and Footer but never force either from view
- 在内容 下方应始终可见
- 这可能意味着在模式的底部(如果 Content 填充剩余空间)或 Content 下方(如果 Content 不填满空间)
- Should always be visible underneath the Content
- This may either mean at the bottom of the modal (if Content fill remaining space) or underneath the Content (if Content doesn't fill space)
虽然这很容易实现(而且我已经这样做了),但问题在于 Content 不应该滚动,而是 inside 应该.下图中是预期行为的两个示例,一个具有应该滚动的长内容,一个没有.
While this would be simple to implement (and I have already done so), the problem arises in the fact that the Content isn't supposed to scroll, but rather something inside it should. In the images below are two example of the intended behaviour, one with long content that should scroll and one without.
我正在使用自定义 Tabbed 组件,该组件在容器内呈现某些内容.这个容器(下图中的白色)是必要时滚动的.
I am using a custom Tabbed component that renders something inside a container. This container (white in the images below) is what should scroll if necessary.
我最远的可以在下面的 CodePen 和示例代码中找到.我目前能够滚动包含预期可滚动内容的元素,但实际上无法滚动该内容.如果您检查 Pen,您会看到它(出于某种原因)延伸到包含元素之外.
The furthest I have come can be found in the following CodePen and example code. I am currently able to scroll the element that contains intended scrollable content, but can't actually get that content to scroll. If you inspect the Pen you can see that it (for some reason) extends past the containing element.
CodePen 示例
<div class="modal">
<div class="background" />
<div class="modal_content">
<div class="header">Random header</div>
<div class="tabbed_content">
<div class="tabs">
<div class="tab active">Tab 1</div>
<div class="tab">Tab 2</div>
</div>
<div class="content">
<div class="scrollable">
Tabbed Content
<br /><br /><br /><br /><br /><br />
Another Couple Lines
<br /><br /><br /><br /><br /><br />
More Tabbed Content
<br /><br /><br /><br /><br /><br />
Even More Content!
<br /><br /><br /><br /><br /><br />
Why not more yet!
<br /><br /><br /><br /><br /><br />
Some Ending Content
<br /><br /><br /><br /><br /><br />
Final Content!
</div>
</div>
</div>
<div class='footer'>
<button class='button'>
Done
</button>
</div>
</div>
</div>
CSS
body {
font-family: 'Montserrat', sans-serif;
}
/* Modal wrapper */
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
/* Modal background styles */
.background {
position: absolute;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.5)
}
/* Modal content */
.modal_content {
height: 100vh;
display: flex;
flex-direction: column;
width: 85%;
margin: 0 auto;
background-color: white;
}
.header {
margin-bottom: 1rem;
padding: 1rem;
font-size: 125%;
text-align: center;
font-weight: bold;
background-color: #EEEEEE;
border-bottom: 1px solid #CECECE;
}
/* Contains the tabs and content */
.tabbed_content {
display: flex;
flex-direction: column;
align-items: stretch;
}
/* IGNORE */
.tabs {
display: flex;
/* NOTE: Added to stop them from hiding */
flex-shrink: 0;
}
/* IGNORE */
.tab {
flex-grow: 1;
margin-top: 8px;
padding: 0.5rem;
text-align: center;
background-color: #CECECE;
}
/* IGNORE */
.tab.active {
margin-top: 0;
font-weight: bold;
background-color: #EEEEEE;
}
/* Contains the current tab's content */
/* NOTE: This shouldn't scroll */
.content {
padding: 1rem;
background-color: #EEEEEE;
/* NOTE: Currently the closest I can come */
/*overflow: auto;*/
}
/* IMPORTANT: This should scroll if necessary! */
.scrollable {
padding: 0.5rem;
background-color: white;
/* NOTE: Can't get this to scroll */
/*overflow: auto;*/
border: 1px dashed #CECECE;
}
.footer {
display: flex;
flex-align: center;
flex-shrink: 0;
justify-content: center;
margin-top: 1rem;
padding: 1rem;
border-top: 1px dashed #CECECE;
}
/* IGNORE */
.button {
padding: 0.75rem 1rem;
font-size: 90%;
color: white;
background-color: lightseagreen;
border: none;
border-radius: 2px;
cursor: pointer;
}
我几乎对此束手无策(到目前为止已经花了 2 个小时搞砸了).提前感谢您的帮助!
I am nearly at my wits end with this (have spent 2 hours messing around so far). Thanks in advance for any help!
附:我还需要担心在某些时候模态打开时停止背景滚动...
P.S. I also need to worry about stopping the background scroll while the modal is open at some point...
推荐答案
一般来说,overflow: auto
要渲染一个垂直滚动条,需要在容器上定义一个高度.
Generally speaking, for overflow: auto
to render a vertical scrollbar, you need to define a height on the container.
为了使 overflow
产生效果,块级容器必须有一个设置的高度(height
或 max-height
) 或 white-space
设置为 nowrap
.
In order for
overflow
to have an effect, the block-level container must have either a set height (height
ormax-height
) orwhite-space
set tonowrap
.
来源:https://developer.mozilla.org/zh-CN/docs/Web/CSS/overflow
但是,这并不总是一个实用的解决方案,尤其是在动态环境中.
However, this isn't always a practical solution, especially in dynamic environments.
在您的布局中,简单的解决方案是使容器 (.content
) 成为 flex 容器.这足以使布局在 Chrome 中工作(demo).
In your layout, the simple solution is to make the container (.content
) a flex container. That's enough to make the layout work in Chrome (demo).
但是,为了使布局也能在 Firefox 和 Edge 中工作,您需要覆盖 flex 项的默认最小高度,即 min-height: auto
.这可以防止弹性项目缩小到其内容大小以下,从而消除了 overflow
发生的可能性.(完整说明)
However, for the layout to also work in Firefox and Edge, you need to override the default minimum height of flex items, which is min-height: auto
. This prevents flex items from shrinking below the size of their content, which eliminates the possibility for an overflow
to occur. (full explanation)
对您的代码进行以下调整:
Make these adjustments to your code:
.tabbed_content {
display: flex;
flex-direction: column;
align-items: stretch;
min-height: 0; /* NEW, esp for FF & Edge (see link below) */
}
.content {
padding: 1rem;
background-color: #EEEEEE;
overflow: auto; /* KEEP THIS, for FF & Edge (see link below) */
display: flex; /* NEW */
flex-direction: column; /* NEW */
}
.scrollable {
padding: 0.5rem;
background-color: white;
overflow: auto; /* RESTORE */
border: 1px dashed #CECECE;
}
修改后的codepen
更多详情:为什么弹性项目不缩小超过内容大小?
相关文章