0

I would like to style a table by pure css whose header could be fixed while body can be scrollable vertically.
This is my demo

/*css for fixed header, vertically scrollable body*/

.fixedHeader {
  width: 100%;
}

.fixedHeader thead {
  display: block;
  width: cal(100% - 17px);
}

.fixedHeader tbody {
  display: block;
  width: 100%;
  max-height: 200px;
  overflow-y: auto;
  overflow-x: hidden;
}


/*custom appearance for your table*/

.fixedHeader {
  border: 1px solid gray;
  border-collapse: collapse;
}

.fixedHeader th,
.fixedHeader td {
  border: 1px solid gray;
}
<table class="fixedHeader">
  <thead>
    <tr>
      <th>Name</th>
      <th>Color</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Apple</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Pear</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Grape</td>
      <td>Purple / Green</td>
      <td>These are purple and green.</td>
    </tr>
    <tr>
      <td>Orange</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Banana</td>
      <td>Yellow</td>
      <td>These are yellow.</td>
    </tr>
    <tr>
      <td>Kiwi</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Plum</td>
      <td>Purple</td>
      <td>These are Purple</td>
    </tr>
    <tr>
      <td>Watermelon</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Tomato</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Cherry</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Cantelope</td>
      <td>Orange</td>
      <td>These are orange inside.</td>
    </tr>
    <tr>
      <td>Honeydew</td>
      <td>Green</td>
      <td>These are green inside.</td>
    </tr>
    <tr>
      <td>Papaya</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Raspberry</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Blueberry</td>
      <td>Blue</td>
      <td>These are blue.</td>
    </tr>
    <tr>
      <td>Mango</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Passion Fruit</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
  </tbody>
</table>

What confused me is that which is the element (perhaps my understandings are totally wrong, please correct me) that the percentage width on td/th refers to on earth?

Abhishek Pandey
  • 13,302
  • 8
  • 38
  • 68
xiyu
  • 11
  • 3
  • Typo in your `width:cal(100% - 17px);`. It must be `calc` not "cal". – divy3993 Mar 27 '17 at 05:57
  • Possible duplicate of [HTML table with 100% width, with vertical scroll inside tbody](http://stackoverflow.com/questions/17067294/html-table-with-100-width-with-vertical-scroll-inside-tbody) – shubham agrawal Mar 27 '17 at 05:58
  • @shubhamagrawal Thanks for your providing. The key here is to adjust the width of th(s) to equal to the width of the corresponding column. But I still don't get that why relative width (percentage) on th/td not working? – xiyu Mar 27 '17 at 14:41

2 Answers2

0

This link: JS Fiddle should work. Try using the CSS on this table to help. Here is the css:

table.scroll {
width: 100%; /* Optional */
/* border-collapse: collapse; */
border-spacing: 0;
border: 2px solid black;
}

table.scroll tbody,
table.scroll thead { display: block; }

thead tr th { 
height: 30px;
line-height: 30px;
/*text-align: left;*/
}

table.scroll tbody {
height: 100px;
overflow-y: auto;
overflow-x: hidden;
}

tbody { border-top: 2px solid black; }

tbody td, thead th {
width: 20%; /* Optional */
border-right: 1px solid black;
}

tbody td:last-child, thead th:last-child {
border-right: none;
}

EDIT

The Javascript is the main key to this:

// Adjust the width of thead cells when window resizes
$(window).resize(function() {
// Get the tbody columns width array
colWidth = $bodyCells.map(function() {
    return $(this).width();
}).get();

// Set the width of thead columns
$table.find('thead tr').children().each(function(i, v) {
    $(v).width(colWidth[i]);
});    
}).resize(); // Trigger resize handler

Hope it helps.

Sank6
  • 491
  • 9
  • 28
0

You can use fixed width td and th and also give position:fixed to thead. So thead will stay at top of table and tbody will scroll.

.fixedHeader{
  width:480px;
   max-height:200px;
  overflow-y:auto;
  overflow-x:hidden;
  display:block;
}
.fixedHeader thead{
  position:fixed;
  background:blue;
  color:white
}
/*custom appearance for your table*/
.fixedHeader{
  border:1px solid gray;
  border-collapse:collapse;
}

.fixedHeader th, .fixedHeader td{
  border:1px solid gray;
  width:150px
}
<table class="fixedHeader">
  <thead>
    <tr>
      <th>Name</th>
      <th>Color</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Apple</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Pear</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Grape</td>
      <td>Purple / Green</td>
      <td>These are purple and green.</td>
    </tr>
    <tr>
      <td>Orange</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Banana</td>
      <td>Yellow</td>
      <td>These are yellow.</td>
    </tr>
    <tr>
      <td>Kiwi</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Plum</td>
      <td>Purple</td>
      <td>These are Purple</td>
    </tr>
    <tr>
      <td>Watermelon</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Tomato</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Cherry</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Cantelope</td>
      <td>Orange</td>
      <td>These are orange inside.</td>
    </tr>
    <tr>
      <td>Honeydew</td>
      <td>Green</td>
      <td>These are green inside.</td>
    </tr>
    <tr>
      <td>Papaya</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Raspberry</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Blueberry</td>
      <td>Blue</td>
      <td>These are blue.</td>
    </tr>
    <tr>
      <td>Mango</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Passion Fruit</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
  </tbody>
</table>
AG_
  • 2,589
  • 3
  • 20
  • 32