问题
I am trying to create a modal with a top, middle and bottom. The top is always fixed height.
The bottom must be "glued" to the bottom and may vary some. All content and elements inside it must build from the bottom. So if there is one line of text, the bottom will be the height of that line. If there are 3 or 4 lines of text, the bottom will push up as needed.
The middle needs to fill up all that is left, and if the content overflow-y
's it must show the scroll bar and not interfere with the top or bottom row.
How would I do this? I'm finding when I try overflow-y: auto
it's not working, presumably because there is not height, but instead it pushes the table outside the bounds of the #wrap
div.
Here is a CodePen: https://codepen.io/sfullman/pen/XGZoJb
body{
font-family: Arial;
}
.table{
display: table;
height: 100%;
width: 100%;
}
.row{
display: table-row;
}
.cell{
display: table-cell;
width: 75%;
}
#top{
background-color: burlywood;
height: 41px;
}
#middle .cell{
overflow-y: scroll;
}
#bottom{
height: 15px; /* make this height less than expected height, table row/cell behavior will successfully exceed it an push content up */
border-top: 1px solid darkred;
background-color: rgba(0,0,0,.15);
}
#wrap{
/* this div is designed to be a dialog/modal and will normally be abs. positioned */
border: 1px solid darkred;
width: 425px;
height: 300px;
position: absolute;
top: 20px;
left: 20px;
}
<div id="wrap">
<div id="innerTable" class="table">
<div id="top" class="row">
<div class="cell">
top
</div>
</div>
<div id="middle" class="row">
<div class="cell">
middle<br>
middle<br>
middle<br>
middle<br>
middle<br>
middle<br>
middle<br>
middle<br>
middle<br>
middle<br>
middle<br>
middle<br>
</div>
</div>
<div id="bottom" class="row">
<div class="cell">
bottom<br>
bottom<br>
bottom<br>
</div>
</div>
</div>
</div>
回答1:
After searching on the web, I found something on JS fiddle which I then modified to create the solution here
Here is the HTML:
<div id="body">
<div id="head">
<!-- if your have content larger than declared height here, it will simply roll under the bottom with no scrolling -->
<p>Fixed size without scrollbar 1</p>
<p>Fixed size without scrollbar 2</p>
<p>Fixed size without scrollbar 3</p>
<p>Fixed size without scrollbar 4</p>
</div>
<div id="content">
<!--
add or remove these to see scrool/non-scroll behavior
-->
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<!--
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
-->
</div>
<div id="foot">
<!-- this content will build from the bottom, pushing the top wall up. #content's bottom will adjust up accordingly -->
<p>Dynamic size without scrollbar 1</p>
<p>Dynamic size without scrollbar 2</p>
<p>Dynamic size without scrollbar 3</p>
</div>
</div>
And the CSS:
#body {
position: absolute;
top: 15px;
left: 15px;
height: 300px;
width: 500px;
outline: black dashed 1px;
display: flex;
flex-direction: column;
}
#head {
/*border: blue solid 1px;*/
background-color: rgba(0,0,255,0.25);
height: 50px;
flex-shrink: 0;
}
#content{
/*border: red solid 1px;*/
background-color: palegoldenrod;
overflow-y: auto;
height: 100%;
}
#foot {
/*border: green solid 1px;*/
background-color: whitesmoke;
flex-shrink: 0;
}
回答2:
I have created an example using flexbox: https://codepen.io/jgoncalves/pen/XGEqoj
.container {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
}
.main {
flex: 1;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
display: flex;
overflow: auto;
}
body {
font-family: sans-serif;
font-size: 20px;
line-height: 50px;
text-transform: uppercase;
font-weight: bold;
}
.header {
text-align: center;
color: #fff;
background: #444;
}
.footer {
padding: 6px 20px;
background: #004141;
color: #fff;
}
.content {
background: #ddd;
}
<div class="container">
<div class="main">
<div class="header">Main header Main headerMain headerMain headerMain headerMain headerMain headerMain header</div>
<div class="content">
Scroll me Scroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll meScroll me
</div>
<div class="footer">Footer end of page. Footer end of page. Footer end of page. Footer end of page. Footer end of page. Footer end of page. Footer end of page. Footer end of page. </div>
</div>
</div>
The center row scrolls while having a fixed header and fixed footer of varying heights.
回答3:
The idea is to have a column flexbox with a max-height
setting that fills the container inside which its kept - see demo below for a full-viewport setup (this is based on this flexbox-based question):
body {
margin: 0;
}
*{
box-sizing: border-box;
}
.row {
display: flex;
flex-direction: column;
max-height: 100vh;
}
.flex {
flex: 1;
overflow-y: auto;
}
.row, .row > * {
border: 1px solid;
}
<div class="row">
<div>some content</div>
<div class="flex">This fills the available space</div>
<!-- fills/grows available space -->
<div>another content</div>
</div>
Note that the height of the header
and footer
can vary dynamically here - this works even if you do not have a fixed height for them. For more complicated layouts, however the newer CSS Grid layouts are preferred as flexboxes are 1D layouts while CSS Grid is a 2D layouting solution - see one example here
Solution
Now I will adapt this to your code - see how it works when there is a lot of content in the middle
section:
body {
font-family: Arial;
}
.table {
display: flex;
flex-direction: column;
max-height: 100%;
width: 100%;
}
.cell {
width: 75%;
}
#top {
background-color: burlywood;
}
#middle {
flex: 1;
overflow-y: auto;
}
#bottom {
border-top: 1px solid darkred;
background-color: rgba(0, 0, 0, .15);
}
#wrap {
border: 1px solid darkred;
width: 425px;
height: 300px;
position: absolute;
top: 20px;
left: 20px;
}
<div id="wrap">
<div id="innerTable" class="table">
<div id="top" class="row">
<div class="cell">
top
</div>
</div>
<div id="middle" class="row">
<div class="cell">
middle<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
</div>
</div>
<div id="bottom" class="row">
<div class="cell">
bottom
</div>
</div>
</div>
</div>
Now see how it works when the content is very less in the middle
section - note how the footer
section is glued to the bottom:
body {
font-family: Arial;
}
.table {
display: flex;
flex-direction: column;
max-height: 100%;
width: 100%;
}
.cell {
width: 75%;
}
#top {
background-color: burlywood;
}
#middle {
flex: 1;
overflow-y: auto;
}
#bottom {
border-top: 1px solid darkred;
background-color: rgba(0, 0, 0, .15);
}
#wrap {
border: 1px solid darkred;
width: 425px;
height: 300px;
position: absolute;
top: 20px;
left: 20px;
}
<div id="wrap">
<div id="innerTable" class="table">
<div id="top" class="row">
<div class="cell">
top
</div>
</div>
<div id="middle" class="row">
<div class="cell">
middle<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
<br> middle
</div>
</div>
<div id="bottom" class="row">
<div class="cell">
bottom
</div>
</div>
</div>
</div>
来源:https://stackoverflow.com/questions/55170715/three-row-modal-with-fixed-with-header-bottom-row-and-scrollable-middle-row