I have a website showing a simple table with weather data. We need to show many rows, so I want to make the body scrollable, while keeping the header fixed.
I have tried a number of solutions, but none of them seem to be compatible with my table header (some header cells have subcategories).
I would like to find a solution based on css and/or javascript. Introducing jQuery or similar would make the site much slower (many of the users have radiolink or satellite internet access).
I have copied part of my code to a JSFiddle
<table>
<thead>
<tr>
<th rowspan="2">Location</th>
<th rowspan="2">Updated</th>
<th colspan="2">Temperature [°C]</th>
<th colspan="2">Wind [m/s]</th>
<th rowspan="2">Air pressure [hPa]</th>
<th rowspan="2">Relative humidity [%]</th>
<th rowspan="2">Precipitation [mm]</th>
</tr>
<tr><th>present</th><th>wind chill</th><th>speed</th><th>max</th> </tr>
</thead>
<tbody>
<tr>
<td>Aasiaat</td>
<td>20.07 15:00</td>
<td>9,3</td>
<td></td>
<td>2,5 ⇙</td>
<td>3,1</td>
<td>1010</td>
<td>87,1</td>
<td>0,0</td>
</tr>
<tr>
<td>Angisoq</td>
<td>20.07 15:00</td>
<td>5,9</td>
<td></td>
<td>3,6 ⇐</td>
<td>4,6</td>
<td>1013</td>
<td>85,0</td>
<td>n/a</td>
</tr>
<tr>
<td>Aasiaat</td>
<td>20.07 15:00</td>
<td>9,3</td>
<td></td>
<td>2,5 ⇙</td>
<td>3,1</td>
<td>1010</td>
<td>87,1</td>
<td>0,0</td>
</tr>
<tr>
<td>Test3</td>
<td>20.07 15:00</td>
<td>9,3</td>
<td></td>
<td>2,5 ⇙</td>
<td>3,1</td>
<td>1010</td>
<td>87,1</td>
<td>0,0</td>
</tr>
<tr>
<td>Test4</td>
<td>20.07 15:00</td>
<td>9,3</td>
<td></td>
<td>2,5 ⇙</td>
<td>3,1</td>
<td>1010</td>
<td>87,1</td>
<td>0,0</td>
</tr>
<tr>
<td>Test5</td>
<td>20.07 15:00</td>
<td>9,3</td>
<td></td>
<td>2,5 ⇙</td>
<td>3,1</td>
<td>1010</td>
<td>87,1</td>
<td>0,0</td>
</tr>
</tbody>
</table>
try this css :
.table-container { height: 20em; width:100% } table { display: flex; flex-flow: column; height: 100%; width: 100%; } table thead { /* head takes the height it requires, and it's not scaled when table is resized */ flex: 0 0 auto; width: calc(100% - 0.9em); } table tbody { /* body takes all the remaining available space */ flex: 1 1 auto; display: block; overflow-y: scroll; } table tbody tr { width: 100%; } table thead, table tbody tr { display: table; table-layout: fixed; } /* decorations */ .table-container { border: 1px solid black; padding: 0.3em; } table { border: 1px solid lightgrey; } table td, table th { padding: 0.3em; border: 1px solid lightgrey; } table th { border: 1px solid grey; }
<div class="table-container"> <table> <thead> <tr> <th rowspan="2">Location</th> <th rowspan="2">Updated</th> <th colspan="2">Temperature [°C]</th> <th colspan="2">Wind [m/s]</th> <th rowspan="2">Air pressure [hPa]</th> <th rowspan="2">Relative humidity [%]</th> <th rowspan="2">Precipitation [mm]</th> </tr> <tr><th>present</th><th>wind chill</th><th>speed</th><th>max</th> </tr> </thead> <tbody> <tr> <td>Aasiaat</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Angisoq</td> <td>20.07 15:00</td> <td>5,9</td> <td></td> <td>3,6 ⇐</td> <td>4,6</td> <td>1013</td> <td>85,0</td> <td>n/a</td> </tr> <tr> <td>Aasiaat</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test3</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test4</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test5</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> </tbody> </table> </div>
You will need javascript to hold/fake table layout properties (row/column adjusting to each others)
Maybe a clone()
jquery + table-layout:fixed
could be a start with evenly spread columns, demo below.
$("table thead ").clone().prependTo("table");
table, th, td, th tr { border: 1px solid black; border-collapse: collapse; border-color: #757575; } /* test */ * { box-sizing: border-box; } body { margin: 0; } table, table thead:first-of-type { width: 100%; table-layout: fixed; /* sprays column evenly when no width set */ } table thead:first-of-type { position: fixed; display: table; top: 0; background: white; left: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <table> <thead> <tr> <th rowspan="2">Location</th> <th rowspan="2">Updated</th> <th colspan="2">Temperature [°C]</th> <th colspan="2">Wind [m/s]</th> <th rowspan="2">Air pressure [hPa]</th> <th rowspan="2">Relative humidity [%]</th> <th rowspan="2">Precipitation [mm]</th> </tr> <tr> <th>present</th> <th>wind chill</th> <th>speed</th> <th>max</th> </tr> </thead> <tbody> <tr> <td>Aasiaat</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Angisoq</td> <td>20.07 15:00</td> <td>5,9</td> <td></td> <td>3,6 ⇐</td> <td>4,6</td> <td>1013</td> <td>85,0</td> <td>n/a</td> </tr> <tr> <td>Aasiaat</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test3</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test4</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test5</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Aasiaat</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Angisoq</td> <td>20.07 15:00</td> <td>5,9</td> <td></td> <td>3,6 ⇐</td> <td>4,6</td> <td>1013</td> <td>85,0</td> <td>n/a</td> </tr> <tr> <td>Aasiaat</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test3</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test4</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test5</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Aasiaat</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Angisoq</td> <td>20.07 15:00</td> <td>5,9</td> <td></td> <td>3,6 ⇐</td> <td>4,6</td> <td>1013</td> <td>85,0</td> <td>n/a</td> </tr> <tr> <td>Aasiaat</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test3</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test4</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test5</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> </tbody> </table>
here body shows the scroll, but it can be a div with a set height, in this case see demo below where things comes a bit more average and tricky ....
$("table thead ").clone().prependTo("table");
table, th, td, th tr { border: 1px solid black; border-collapse: collapse; border-color: #757575; } /* test */ *{box-sizing:border-box; } div { position:relative; width : 700px; padding-right:1em; height:200px; } div div {/* buffer for positionning*/ position:static; padding:0; height:100%; overflow:auto; } table, table thead:first-of-type { width: 100%; table-layout: fixed; /* sprays column evenly when no width set */ } table thead:first-of-type { position: absolute; width: calc(100% - 1em - 1px); display: table; top: 0; background: white; left: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div><div> <table> <thead> <tr> <th rowspan="2">Location</th> <th rowspan="2">Updated</th> <th colspan="2">Temperature [°C]</th> <th colspan="2">Wind [m/s]</th> <th rowspan="2">Air pressure [hPa]</th> <th rowspan="2">Relative humidity [%]</th> <th rowspan="2">Precipitation [mm]</th> </tr> <tr> <th>present</th> <th>wind chill</th> <th>speed</th> <th>max</th> </tr> </thead> <tbody> <tr> <td>Aasiaat</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Angisoq</td> <td>20.07 15:00</td> <td>5,9</td> <td></td> <td>3,6 ⇐</td> <td>4,6</td> <td>1013</td> <td>85,0</td> <td>n/a</td> </tr> <tr> <td>Aasiaat</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test3</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test4</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> <tr> <td>Test5</td> <td>20.07 15:00</td> <td>9,3</td> <td></td> <td>2,5 ⇙</td> <td>3,1</td> <td>1010</td> <td>87,1</td> <td>0,0</td> </tr> </tbody> </table> </div> </div>
I drew up a quick codepen for you to see.
Here's the idea:
Remove the table header, and replace it with a fixed container that emulates the header. Give table a height, and make overflow scroll.
Markup:
<ul class="table-header">
<li>Location</li>
<li>Updated</li>
<li>
Temperature
<ul>
<li>present</li>
<li>wind chill</li>
</ul>
</li>
<li>
Wind
<ul>
<li>speed</li>
<li>max</li>
</ul>
</li>
<li>Air pressure</li>
<li>Relative humidity</li>
<li>Precipitation</li>
</ul>
css:
table {
width: 100%;
margin-top: 60px;
overflow: scroll;
max-height: 200px;
}
.table-header {
background-color: white;
position: fixed;
top: 0;
left: 0;
list-style: none;
display: flex;
padding-left: 0;
justify-content: space-around;
width: 100%;
li {
font-size: 1em;
font-weight: 600;
flex-grow: 1;
text-align: center;
}
ul {
display: flex;
list-style: none;
padding-left: 0;
li {
text-align: center;
flex-grow: 1;
}
}
}
It's not perfect, but you get the idea. You just have to play around with flex basis and make the top container look like the table header.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.