Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set tbody height with overflow scroll

Tags:

html

css

People also ask

How do I make my table body scrollable in HTML?

We set the height of the table element to 120px to make restrict the height of it so we can make it scrollable. To make it scrollable, we set the overflow CSS property to scroll . Then we set the tr elements in the thead to absolute position so they stay in place.

How do you define minimum height for Tbody in CSS?

Min-height and height applies to block level elements and table isn't a block level element. Wrap your table inside a div (say div. table-wrap) and apply minimum height to that div. If you don't want table layout isn't important to you, then just add display:block to the CSS of tbody.

How do I add a vertical scrollbar to a table?

use overflow-y if you only want a vertical scroll bar and overflow if you want both a vertical and horizontal. Note: setting an overflow attribute to scroll will always display the scrollbars. If you want the horizontal/vertical scrollbars to only show up when needed, use auto .


If you want tbody to show a scrollbar, set its display: block;.

Set display: table; for the tr so that it keeps the behavior of a table.

To evenly spread the cells, use table-layout: fixed;.

DEMO tbody scroll


CSS:

table, tr td {
    border: 1px solid red
}
tbody {
    display: block;
    height: 50px;
    overflow: auto;
}
thead, tbody tr {
    display: table;
    width: 100%;
    table-layout: fixed;/* even columns width , fix width of table too*/
}
thead {
    width: calc( 100% - 1em )/* scrollbar is average 1em/16px width, remove it from thead width */
}
table {
    width: 400px;
}

If tbody doesn't show a scroll, because content is less than height or max-height, set the scroll any time with: overflow-y: scroll;. DEMO 2


<editS/updateS> 2019 - 04/2021


  • Important note: this approach to making a table scrollable has drawbacks in some cases. (See comments below.) some of the duplicate answers in this thread deserves the same warning by the way

WARNING: this solution disconnects the thead and tbody cell grids; which means that in most practical cases, you will not have the cell alignment you expect from tables. Notice this solution uses a hack to keep them sort-of aligned: thead { width: calc( 100% - 1em ) }

  • Anyhow, to set a scrollbar, a display reset is needed to get rid of the table-layout (which will never show scrollbar).

  • Turning the <table> into a grid via display:grid/contents will also leave a gap in between header and scrollable part, to mind about. (idem if built from divs)

  • overflow:overlay; has not yet shown up in Firefox ( keep watching it)

  • position:sticky will require a parent container which can be the scrolling one. make sure your thead can be sticky if you have a few rows and rowspan/colspan headers in it (it does not with chrome).

So far, there is no perfect solution yet via CSS only. there is a few average ways to choose along so it fits your own table (table-layout:fixed; is .. fixing table and column's width, but javascript could probably be used to reset those values => exit pure CSS)


It is simple way to use scroll bar to table body

/* It is simple way to use scroll bar to table body*/

table tbody {
  display: block;
  max-height: 300px;
  overflow-y: scroll;
}

table thead, table tbody tr {
  display: table;
  width: 100%;
  table-layout: fixed;
}
<table>
  <thead>
    <th>Invoice Number</th>
    <th>Purchaser</th>
    <th>Invoice Amount</th>
    <th>Invoice Date</th>
  </thead>
  <tbody>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
    <tr>
      <td>INV-1233</td>
      <td>Dinesh Vaitage</td>
      <td>$300</td>
      <td>01/12/2017</td>
    </tr>
  </tbody>
</table>

Another approach is to wrap your table in a scrollable element and set the header cells to stick to the top.

The advantage of this approach is that you don't have to change the display on tbody and you can leave it to the browser to calculate column width while keeping the header cell widths in line with the data cell column widths.

/* Set a fixed scrollable wrapper */
.tableWrap {
  height: 200px;
  border: 2px solid black;
  overflow: auto;
}
/* Set header to stick to the top of the container. */
thead tr th {
  position: sticky;
  top: 0;
}

/* If we use border,
we must use table-collapse to avoid
a slight movement of the header row */
table {
 border-collapse: collapse;
}

/* Because we must set sticky on th,
 we have to apply background styles here
 rather than on thead */
th {
  padding: 16px;
  padding-left: 15px;
  border-left: 1px dotted rgba(200, 209, 224, 0.6);
  border-bottom: 1px solid #e8e8e8;
  background: #ffc491;
  text-align: left;
  /* With border-collapse, we must use box-shadow or psuedo elements
  for the header borders */
  box-shadow: 0px 0px 0 2px #e8e8e8;
}

/* Basic Demo styling */
table {
  width: 100%;
  font-family: sans-serif;
}
table td {
  padding: 16px;
}
tbody tr {
  border-bottom: 2px solid #e8e8e8;
}
thead {
  font-weight: 500;
  color: rgba(0, 0, 0, 0.85);
}
tbody tr:hover {
  background: #e6f7ff;
}
<div class="tableWrap">
  <table>
    <thead>
      <tr>
        <th><span>Month</span></th>
        <th>
          <span>Event</span>
        </th>
        <th><span>Action</span></th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>January</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>February. An extra long string.</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>March</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>April</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>May</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>June</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>July</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>August</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>September</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>October</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>November</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
      <tr>
        <td>December</td>
        <td>AAA</td>
        <td><span>Invite | Delete</span></td>
      </tr>
    </tbody>
  </table>
</div>

By default overflow does not apply to table group elements unless you give a display:block to <tbody> also you have to give a position:relative and display: block to <thead>. Check the DEMO.

.fixed {
  width:350px;
  table-layout: fixed;
  border-collapse: collapse;
}
.fixed th {
  text-decoration: underline;
}
.fixed th,
.fixed td {
  padding: 5px;
  text-align: left;
  min-width: 200px;
}


.fixed thead {
  background-color: red;
  color: #fdfdfd;
}
.fixed thead tr {
  display: block;
  position: relative;
}
.fixed tbody {
  display: block;
  overflow: auto;
  width: 100%;
  height: 100px;
  overflow-y: scroll;
    overflow-x: hidden;
}

Simplest of all solutions:

Add the below code in CSS:

.tableClassName tbody {
  display: block;
  max-height: 200px;
  overflow-y: scroll;
}

.tableClassName thead, .tableClassName tbody tr {
  display: table;
  width: 100%;
  table-layout: fixed;
}
.tableClassName thead {
  width: calc( 100% - 1.1em );
}

1.1 em is the average width of the scroll bar, please modify this if needed.


Based on this answer, here's a minimal solution if you're already using Bootstrap:

div.scrollable-table-wrapper {
  height: 500px;
  overflow: auto;

  thead tr th {
    position: sticky;
    top: 0;
  }
}
<div class="scrollable-table-wrapper">
  <table class="table">
    <thead>...</thead>
    <tbody>...</tbody>
  </table>
</div>

Tested on Bootstrap v3