I am trying to scroll div element with class o-body and fit space between o-header and o-footer. But the element with class o-footer has dynamically height, the height depends on number of elements in buttons collection. How make element with class o-body scrollable and its height changed based on height of element with class o-footer. Sorry my english.
.o-container {
position: relative;
height: 200px;
}
.o-header {
position: relative;
vertical-align: top;
}
.o-body {
position: absolute;
overflow-y: scroll;
height: 100px;
}
.o-footer {
position: absolute;
bottom: 0px;
}
<div >
<div >
<div>
headerrow1
</div>
<div>
headerrow2
</div>
</div>
<div >
<div>
bodyrow1
</div>
<div>
bodyrow2
</div>
<div>
bodyrow3
</div>
<div>
bodyrow4
</div>
<div>
bodyrow5
</div>
<div>
bodyrow6
</div>
<div>
bodyrow7
</div>
<div>
bodyrow8
</div>
</div>
<div >
<div data-bind="foreach: buttons">
<div>
footerrow1
</div>
<div>
footerrow2
</div>
</div>
</div>
</div>
CodePudding user response:
The usage of position: relative/absolute
is a bit off putting as it inhibits a proper solution to your problem.
Containers .o-container
and .o-footer
need to be able to grow, where .o-header
and .o-body
containers do not.
There is no plain CSS way to resize container .o-body
based on the number of buttons inside .o-footer
. You cannot simply say something like .o-body { height: calc((.o-footer.child-count - 2) * 1rem)
. You will need Javascript for that.
We can simplify things somewhat by using CSS custom properties. I introduced CSS variable --rows
which has to be changed to the required number of rows when a button gets added to .o-footer
. This way both .o-body
and .o-footer
can grow without overlapping.
The simple JS for --rows
is document.body.style.setProperty('--rows', requiredRows);
In below snippet I removed all the position: relative/absolute
references and created a (commented) base structure you can use. Including easy access to some generic document line-height (--lh
) and padding (--pd
) CSS variables.
No JS as I don't know how the buttons get added to .o-footer
...
Snippet
body {
--lh : 1.5; /* document default line height */
--pd : 0.5rem; /* some default padding (inner spacing) */
--rows: 7; /* # of rows visible in .o-body */
line-height: var(--lh);
}
.o-container {
display: flex; flex-flow: column wrap;
padding: var(--pd);
width: 8rem; /* some width you require */
}
.o-container .o-header { padding-bottom: var(--pd) }
.o-container .o-footer { padding-top : var(--pd) }
.o-body {
overflow-y: auto;
/* calculate height relative to lh and rows in REM */
height: calc(var(--lh) * var(--rows) * 1rem);
}
<div >
<div >
<div>header row1</div>
<div>header row2</div>
</div>
<div >
<div>body row1</div>
<div>body row2</div>
<div>body row3</div>
<div>body row4</div>
<div>body row5</div>
<div>body row6</div>
<div>body row7</div>
<div>body row8</div>
<div>body row9</div>
<div>body row10</div>
<div>body row11</div>
<div>body row12</div>
<div>body row13</div>
</div>
<div >
<div data-bind="foreach: buttons">
<div>footer row1</div>
<div>footer row2</div>
<div>footer row3</div>
<div>footer row4</div>
<div>footer row5</div>
<div>footer row6</div>
</div>
</div>
</div>
CodePudding user response:
Is this what you mean? I have added comments in the code to make it more clear, hope this help!
.o-container {
position: relative;
height: 200px;
}
.o-header {
position: relative;
vertical-align: top;
}
.o-body {
position: relative; /* change this from absolute to relative */
/* overflow-y: scroll; */
height: auto; /* change the height to be auto */
}
.o-footer {
position: relative; /* change this from absolute to relative */
/* bottom: 0px; */
}
<div >
<div >
<div>
headerrow1
</div>
<div>
headerrow2
</div>
</div>
<div >
<div>
bodyrow1
</div>
<div>
bodyrow2
</div>
<div>
bodyrow3
</div>
<div>
bodyrow4
</div>
<div>
bodyrow5
</div>
<div>
bodyrow6
</div>
<div>
bodyrow7
</div>
<div>
bodyrow8
</div>
</div>
<div >
<div data-bind="foreach: buttons">
<div>
footerrow1
</div>
<div>
footerrow2
</div>
</div>
</div>
</div>