You can try to set both scroll bars on table
, and set .container
position as absolute
and tableHeader
as sticky
with top: 0;
. For cells background, set background-color
on tableCell
and add class for header cell with another background-color
:
#container {
width: 400px;
height: 200px;
display: flex;
flex-direction: column;
position: absolute;
}
#header, #footer {
background-color: #666;
}
#table {
overflow-x: scroll;
overflow-y: scroll;
display: grid;
}
#tableHeader {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
position: sticky;
top: 0;
}
.head {
background-color: #AAA !important;
}
#tableBody {
display: flex;
flex-direction: column;
}
.tableRow {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
background-color: #DDD;
}
.tableRow:nth-child(odd) {
background-color: #40E0D0;
}
.tableRow:nth-child(even) {
background-color: violet;
}
.tableCell {
padding: 4px;
width: 300px;
flex-shrink: 0;
border: solid 1px black;
/* background-color: #DDD;*/
}
.fixedSize {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="container">
<div id="header">Header</div>
<div id="table">
<div id="tableHeader">
<div class="tableCell head">Column1</div>
<div class="tableCell head">Column2</div>
<div class="tableCell head">Column3</div>
<div class="tableCell head">Column4</div>
</div>
<div id="tableBody">
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
</div>
</div>
<div id="footer">Footer</div>
</div>
First You need to define which container will provide scrolls – since that is table
give it overflow: scroll
to allow scroll its contents in both axis.
If You need to stick table header in place – use ‘sticky’ positioning (commented in code example) or absolute with top
/left
/right
0 to tableHeader, and for tableBody relative
positioning in couple with padding
equal to tableHeader height value
Then all BIG DATA placed in appropriate container should be protected from shrinking with overflow:visible
to be drawn correctly.
#container {
width: 400px;
height: 200px;
display: flex;
flex-direction: column;
}
#header, #footer {
background-color: #666;
}
#table {
overflow: scroll;
}
#tableHeader {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
background-color: #AAA;
/* uncomment it if header sticky position needed
position:sticky;
top:0;
*/
}
#tableBody {
display: flex;
flex-direction: column;
overflow: visible;
}
.tableRow {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.tableCell {
padding: 4px;
width: 300px;
flex-shrink: 0;
border: solid 1px black;
background-color: #DDD;
}
.fixedSize {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="container">
<div id="header">Header</div>
<div id="table">
<div id="tableHeader">
<div class="tableCell">Column1</div>
<div class="tableCell">Column2</div>
<div class="tableCell">Column3</div>
<div class="tableCell">Column4</div>
</div>
<div id="tableBody">
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
</div>
</div>
<div id="footer">Footer</div>
</div>
See if this meets the requirements. No positioning like fixed
or absolute
needed:
* {
padding: 0;
margin: 0;
}
#container {
width: 400px;
height: 200px;
display: flex;
flex-direction: column;
}
#header,
#footer {
background-color: #666;
}
#table {
overflow: auto;
}
#tableHeader {
display: flex;
flex-direction: row;
flex-wrap: wrap;
background-color: #AAA;
}
#tableBody {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.tableRow {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
background-color: #DDD;
}
.tableCell {
padding: 4px;
width: 300px;
flex-shrink: 0;
border: solid 1px black;
}
.fixedSize {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="container">
<div id="header">Header</div>
<div id="table">
<div id="tableHeader">
<div class="tableRow">
<div class="tableCell">Column1</div>
<div class="tableCell">Column2</div>
<div class="tableCell">Column3</div>
<div class="tableCell">Column4</div>
</div>
<div id="tableBody">
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
</div>
</div>
</div>
<div id="footer">Footer</div>
</div>
I am struggling to get my flexbox layout to scroll as I need. My requirements are:
- Fixed size container
- Fixed header and footer
- Table to scroll horizontally
- Table body to scroll vertically
I am hoping to do the above with only defining the sizes of:
- The container width/height
- The cell width
- Cell content height (the blue squares in the below fiddle).
Is this possible or do I need to define more widths/heights? In the fiddle I also notice that when the table scrolls horizontally, the background colours are lost. How can this be conserved? Link to the fiddle:
https://jsfiddle.net/talbot82/83wrktvb/6/
HTML:
<div id="container">
<div id="header">Header</div>
<div id="table">
<div id="tableHeader">
<div class="tableCell">Column1</div>
<div class="tableCell">Column2</div>
<div class="tableCell">Column3</div>
<div class="tableCell">Column4</div>
</div>
<div id="tableBody">
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
<div class="tableRow">
<div class="tableCell">
<div class="fixedSize"></div>
</div>
<div class="tableCell"></div>
<div class="tableCell"></div>
<div class="tableCell"></div>
</div>
</div>
</div>
<div id="footer">Footer</div>
</div>
CSS:
#container {
width: 400px;
height: 200px;
display: flex;
flex-direction: column;
}
#header, #footer {
background-color: #666;
}
#table {
overflow-x: scroll;
overflow-y: hidden;
}
#tableHeader {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
background-color: #AAA;
}
#tableBody {
display: flex;
flex-direction: column;
overflow-y: scroll;
}
.tableRow {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
background-color: #DDD;
}
.tableCell {
padding: 4px;
width: 300px;
flex-shrink: 0;
border: solid 1px black;
}
.fixedSize {
width: 40px;
height: 40px;
background-color: blue;
}
This is great, but I need to be able to set the row colour rather than cell, as in my real project I have alternating row colours. Sorry this info wasn’t included in the question.
hey mate, i think he wants only table body to be scrollable, not table Header, or i miss understood completely , cheers 🙂
@NikolaPavicevic – Ya, I’m not sure. I like your fixed table header. If he doesn’t use it, I will!
Yes, that’s right, I want the table header to only scroll horizontally header. I appreciate the suggestion though!