Qaisa
Qaisa

Reputation: 49

Scrollable table body and fixed header

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 &#8665;</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 &#8656;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8665;</td>
    <td>3,1</td>
    <td>1010</td>
    <td>87,1</td>
    <td>0,0</td>
  </tr>
 </tbody>
</table>

Upvotes: 0

Views: 936

Answers (3)

zsawaf
zsawaf

Reputation: 2001

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.

http://codepen.io/zsawaf/pen/mExAak

Upvotes: 0

G-Cyrillus
G-Cyrillus

Reputation: 105893

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 &#8665;</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 &#8656;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8656;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8656;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8656;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8665;</td>
        <td>3,1</td>
        <td>1010</td>
        <td>87,1</td>
        <td>0,0</td>
      </tr>
    </tbody>
  </table>
  </div>    
  </div>    

Upvotes: 0

Vaibhav
Vaibhav

Reputation: 1234

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 &#8665;</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 &#8656;</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 &#8665;</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 &#8665;</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 &#8665;</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 &#8665;</td>
    <td>3,1</td>
    <td>1010</td>
    <td>87,1</td>
    <td>0,0</td>
  </tr>
 </tbody>
</table>

</div>

Upvotes: 3

Related Questions