I've tried many different approaches to make a table body scrolling, while having a fixed table header - none of them worked really satisfying, so finally I ended up using a table for the header, and a second table for the body, that is placed within a scrolling container. This works, as long as I give the scrollable container that contains the table body a fixed height.
Now I want a flexible height, so I'm trying with flex:
/* SOME BASE CSS SETTINGS */
* {
box-sizing: border-box;
}
body,
html {
color: white;
width: 100%;
height: 100%;
padding: 0px;
margin: 0px;
}
/* A FLEX COLUMN CONTAINER */
.flexContainer {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: stretch;
}
/* FLEX ELEMENT THAT SHOULD GROW TO FIT THE AVAILABLE SPACE */
.flexGrow {
flex-grow: 1;
}
/* SECTION ONE IS HIDDEN, BUT EXISTS IN REAL LIFE */
#S1 {
display: none;
visibility: hidden;
}
#S1>header {
background-color: red;
min-height: 450px;
}
#S1>main {
background-color: green;
overflow: auto;
min-height: calc(100% - 550px);
max-height: calc(100% - 550px);
}
#S1>footer {
background-color: blue;
min-height: 100px;
}
/* SECTION 2 IS VISIBLE */
#S2>header {
background-color: red;
min-height: 150px;
}
#S2>main {
background-color: green;
/* If I remove this, MAIN won't be displayed beside NAV */
display: inline-block;
/* If I remove this, the document body will scroll :( */
min-height: calc(100% - 250px);
max-height: calc(100% - 250px);
}
#S2>main>div {
flex-direction: row;
}
#S2>main>div>nav {
background-color: black;
min-width: 450px;
}
#S2>main>div>section {
background-color: teal;
width: 100%;
height: 100%;
/* If I remove this, the body will scroll the big table of sub section 1! */
overflow: auto;
}
#S2>footer {
background-color: blue;
min-height: 100px;
}
/* SUB SECTION 1 IS VISIBLE */
#SS1 {
border: 5px solid green;
}
#SS1>div {
background-color: turquoise;
border: 5px solid turquoise;
}
#SS1>div>.table {
/* Why does this overflow!? It should only fill the available space. */
background-color: violet;
border: 5px solid violet;
width: 100%;
}
#SS1>div>.table>.container {
background-color: wheat;
border: 5px solid wheat;
}
#SS1>div>.table>.container>.header {
background-color: silver;
border: 5px solid silver;
width: 100%;
height: 40px;
}
#SS1>div>.table>.container>.data {
background-color: yellowgreen;
border: 5px solid yellowgreen;
width: 100%;
}
#SS1>div>.table>.container>.data>.container {
background-color: cadetblue;
border: 5px solid cadetblue;
width: 100%;
height: 100%;
/* This scrolling should be applied to have a fixed header and a scrolling body - but instead the sub section is scrolling :S */
overflow-y: auto;
}
#SS1>div>.table>.container>.data>.container>.body {
background-color: brown;
border: 5px solid brown;
width: 100%;
}
#SS1>div>.table>.container>.data>.container>.body tr {
height: 200px;
/* Ensure the table data will overflow */
}
#SS1>div>.table td {
width: 150px;
}
#SS1>div>.table td:nth-child(2) {
width: auto;
}
/* SUB SECTION 2 IS HIDDEN, BUT EXISTS IN REAL LIFE */
#SS2 {
display: none;
visibility: hidden;
}
<!DOCTYPE html>
<body>
<section id="S1" class="flexContainer">
<header>S1 HEADER</header>
<main class="flexGrow">S1 MAIN</main>
<footer>S1 FOOTER</footer>
</section>
<section id="S2" class="flexContainer">
<header>S2 HEADER</header>
<main class="flexGrow">
<div class="flexContainer">
<nav>S2 NAV</nav>
<section id="SS1" class="flexGrow">
<div class="flexContainer">
<h1>S2 SECTION 2</h1>
<div class="table flexGrow">
<div class="container flexContainer">
<table class="header">
<thead>
<tr>
<td>Column 1</td>
<td>Column 2</td>
<td>Column 3</td>
<td>Column 4</td>
<td>Column 5</td>
</tr>
</thead>
</table>
<div class="data flexGrow">
<div class="container">
<table class="body">
<tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 5</td>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 5</td>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 5</td>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 5</td>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 5</td>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 5</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="SS2">S2 SECTION 2</section>
</div>
</main>
<footer>S2 FOOTER</footer>
</section>
</body>
But there are several problems with the result:
- The violet container should only fit the available space, but not overflow!
- The same with the yellow green container
- The cadet blue container contains the table and should scroll, because the table does overflow - but it doesn't scroll
And there are some more things, that I don't really like/understand:
- Why has
#S2>main
to beinline-block
to be displayed beside#S2>nav
? - Why do I have to give
#S2>main
a height? I assumed the height will fit to the available height, but if I don't give a height, the document will scroll
Finally the most important thing for me is: How can I avoid the scrolling of the turquoise container and force the cadet blue container to scroll the overflowing content?
Edit: Thanks to "David says reinstate Monica" for reformatting HTML & CSS :) Thanks to G-Cyrillus I was able to get what I want just by adding min-height:0px;
to the flexGrow
CSS class. And of course I'll overwork my fixed table header solution to become sticky...