[html] How to display scroll bar onto a html table

I am writing a page where I need an html table to maintain a set size. I need the headers at the top of the table to stay there at all times but I also need the body of the table to scroll no matter how many rows are added to the table.

I want it to look like method 2 in this url: http://www.cssplay.co.uk/menu/tablescroll.html

I have tried doing this but no scrollbar appears:

_x000D_
_x000D_
tbody {
  height: 80em;
  overflow: scroll;
}
_x000D_
<table border=1 id="qandatbl" align="center">
  <tr>
    <th class="col1">Question No</th>
    <th class="col2">Option Type</th>
    <th class="col1">Duration</th>
  </tr>

  <tbody>
    <tr>
      <td class='qid'></td>
      <td class="options"></td>
      <td class="duration"></td>
    </tr>
  </tbody>
</table>
_x000D_
_x000D_
_x000D_

This question is related to html css scroll html-table overflow

The answer is


just add on table

style="overflow-x:auto;"

_x000D_
_x000D_
<table border=1 id="qandatbl" align="center" style="overflow-x:auto;">_x000D_
    <tr>_x000D_
    <th class="col1">Question No</th>_x000D_
    <th class="col2">Option Type</th>_x000D_
    <th class="col1">Duration</th>_x000D_
    </tr>_x000D_
_x000D_
   <tbody>_x000D_
    <tr>_x000D_
    <td class='qid'></td>_x000D_
    <td class="options"></td>_x000D_
    <td class="duration"></td>_x000D_
    </tr>_x000D_
    </tbody>_x000D_
</table>
_x000D_
_x000D_
_x000D_

style="overflow-x:auto;"`


The accepted answer provided a good starting point, but if you resize the frame, change the column widths, or even change the table data, the headers will get messed up in various ways. Every other example I've seen has similar issues, or imposes some serious restrictions on the table's layout.

I think I've finally got all these problems solved, though. It took a lot of CSS, but the final product is about as reliable and easy to use as a normal table.

Here's an example that has all the required features to replicate the table referenced by the OP: jsFiddle

The colors and borders would have to be changed to make it identical to the reference. Information on how to make those kinds of changes is provided in the CSS comments.

Here's the code:

_x000D_
_x000D_
/*the following html and body rule sets are required only if using a % width or height*/_x000D_
/*html {_x000D_
width: 100%;_x000D_
height: 100%;_x000D_
}*/_x000D_
body {_x000D_
  box-sizing: border-box;_x000D_
  width: 100%;_x000D_
  height: 100%;_x000D_
  margin: 0;_x000D_
  padding: 0 20px 0 20px;_x000D_
  text-align: center;_x000D_
  background: white;_x000D_
}_x000D_
.scrollingtable {_x000D_
  box-sizing: border-box;_x000D_
  display: inline-block;_x000D_
  vertical-align: middle;_x000D_
  overflow: hidden;_x000D_
  width: auto; /*if you want a fixed width, set it here, else set to auto*/_x000D_
  min-width: 0/*100%*/; /*if you want a % width, set it here, else set to 0*/_x000D_
  height: 188px/*100%*/; /*set table height here; can be fixed value or %*/_x000D_
  min-height: 0/*104px*/; /*if using % height, make this large enough to fit scrollbar arrows + caption + thead*/_x000D_
  font-family: Verdana, Tahoma, sans-serif;_x000D_
  font-size: 15px;_x000D_
  line-height: 20px;_x000D_
  padding: 20px 0 20px 0; /*need enough padding to make room for caption*/_x000D_
  text-align: left;_x000D_
}_x000D_
.scrollingtable * {box-sizing: border-box;}_x000D_
.scrollingtable > div {_x000D_
  position: relative;_x000D_
  border-top: 1px solid black;_x000D_
  height: 100%;_x000D_
  padding-top: 20px; /*this determines column header height*/_x000D_
}_x000D_
.scrollingtable > div:before {_x000D_
  top: 0;_x000D_
  background: cornflowerblue; /*header row background color*/_x000D_
}_x000D_
.scrollingtable > div:before,_x000D_
.scrollingtable > div > div:after {_x000D_
  content: "";_x000D_
  position: absolute;_x000D_
  z-index: -1;_x000D_
  width: 100%;_x000D_
  height: 100%;_x000D_
  left: 0;_x000D_
}_x000D_
.scrollingtable > div > div {_x000D_
  min-height: 0/*43px*/; /*if using % height, make this large enough to fit scrollbar arrows*/_x000D_
  max-height: 100%;_x000D_
  overflow: scroll/*auto*/; /*set to auto if using fixed or % width; else scroll*/_x000D_
  overflow-x: hidden;_x000D_
  border: 1px solid black; /*border around table body*/_x000D_
}_x000D_
.scrollingtable > div > div:after {background: white;} /*match page background color*/_x000D_
.scrollingtable > div > div > table {_x000D_
  width: 100%;_x000D_
  border-spacing: 0;_x000D_
  margin-top: -20px; /*inverse of column header height*/_x000D_
  /*margin-right: 17px;*/ /*uncomment if using % width*/_x000D_
}_x000D_
.scrollingtable > div > div > table > caption {_x000D_
  position: absolute;_x000D_
  top: -20px; /*inverse of caption height*/_x000D_
  margin-top: -1px; /*inverse of border-width*/_x000D_
  width: 100%;_x000D_
  font-weight: bold;_x000D_
  text-align: center;_x000D_
}_x000D_
.scrollingtable > div > div > table > * > tr > * {padding: 0;}_x000D_
.scrollingtable > div > div > table > thead {_x000D_
  vertical-align: bottom;_x000D_
  white-space: nowrap;_x000D_
  text-align: center;_x000D_
}_x000D_
.scrollingtable > div > div > table > thead > tr > * > div {_x000D_
  display: inline-block;_x000D_
  padding: 0 6px 0 6px; /*header cell padding*/_x000D_
}_x000D_
.scrollingtable > div > div > table > thead > tr > :first-child:before {_x000D_
  content: "";_x000D_
  position: absolute;_x000D_
  top: 0;_x000D_
  left: 0;_x000D_
  height: 20px; /*match column header height*/_x000D_
  border-left: 1px solid black; /*leftmost header border*/_x000D_
}_x000D_
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,_x000D_
.scrollingtable > div > div > table > thead > tr > * > div > div:first-child,_x000D_
.scrollingtable > div > div > table > thead > tr > * + :before {_x000D_
  position: absolute;_x000D_
  top: 0;_x000D_
  white-space: pre-wrap;_x000D_
  color: white; /*header row font color*/_x000D_
}_x000D_
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,_x000D_
.scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);}_x000D_
.scrollingtable > div > div > table > thead > tr > * + :before {_x000D_
  content: "";_x000D_
  display: block;_x000D_
  min-height: 20px; /*match column header height*/_x000D_
  padding-top: 1px;_x000D_
  border-left: 1px solid black; /*borders between header cells*/_x000D_
}_x000D_
.scrollingtable .scrollbarhead {float: right;}_x000D_
.scrollingtable .scrollbarhead:before {_x000D_
  position: absolute;_x000D_
  width: 100px;_x000D_
  top: -1px; /*inverse border-width*/_x000D_
  background: white; /*match page background color*/_x000D_
}_x000D_
.scrollingtable > div > div > table > tbody > tr:after {_x000D_
  content: "";_x000D_
  display: table-cell;_x000D_
  position: relative;_x000D_
  padding: 0;_x000D_
  border-top: 1px solid black;_x000D_
  top: -1px; /*inverse of border width*/_x000D_
}_x000D_
.scrollingtable > div > div > table > tbody {vertical-align: top;}_x000D_
.scrollingtable > div > div > table > tbody > tr {background: white;}_x000D_
.scrollingtable > div > div > table > tbody > tr > * {_x000D_
  border-bottom: 1px solid black;_x000D_
  padding: 0 6px 0 6px;_x000D_
  height: 20px; /*match column header height*/_x000D_
}_x000D_
.scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;}_x000D_
.scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /*alternate row color*/_x000D_
.scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /*borders between body cells*/
_x000D_
<div class="scrollingtable">_x000D_
  <div>_x000D_
    <div>_x000D_
      <table>_x000D_
        <caption>Top Caption</caption>_x000D_
        <thead>_x000D_
          <tr>_x000D_
            <th><div label="Column 1"></div></th>_x000D_
            <th><div label="Column 2"></div></th>_x000D_
            <th><div label="Column 3"></div></th>_x000D_
            <th>_x000D_
              <!--more versatile way of doing column label; requires 2 identical copies of label-->_x000D_
              <div><div>Column 4</div><div>Column 4</div></div>_x000D_
            </th>_x000D_
            <th class="scrollbarhead"/> <!--ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW-->_x000D_
          </tr>_x000D_
        </thead>_x000D_
        <tbody>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>_x000D_
        </tbody>_x000D_
      </table>_x000D_
    </div>_x000D_
    Faux bottom caption_x000D_
  </div>_x000D_
</div>_x000D_
_x000D_
<!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->
_x000D_
_x000D_
_x000D_


The CSS: div{ overflow-y:scroll; overflow-x:scroll; width:20px; height:30px; } table{ width:50px; height:50px; }

You can make the table and the DIV around the table be any size you want, just make sure that the DIV is smaller than the table. You MUST contain the table inside of the DIV.


I resolved this problem by separating my content into two tables.

One table is the header row.

The seconds is also <table> tag, but wrapped by <div> with static height and overflow scroll.


Not sure why no one mentioned to just use the built-in sticky header style for elements. Worked great for me.

.tableContainerDiv {
   overflow: auto;
   max-height: 80em;
}
th {
   position: sticky;
   top: 0;
   background: white;
}

Put a min-width on the in @media if you need to make responsive (or similar).

see Table headers position:sticky or Position Sticky and Table Headers


Very easy, just wrap the table in a div that has overflow-y:scroll; and overflow-x:scroll properties, and make the div have a width and length smaller than the table. IT WILL WORK!!!


If you get to the point where all the mentioned solutions don't work (as it got for me), do this:

  • Create two tables. One for the header and another for the body
  • Give the two tables different parent containers/divs
  • Style the second table's div to allow vertical scroll of its contents.

Like this, in your HTML

<div class="table-header-class">
    <table>
       <thead>
          <tr>
            <th>Ava</th>
            <th>Alexis</th>
            <th>Mcclure</th>
          </tr>
       </thead>
    </table>
</div>
<div class="table-content-class">
   <table>
       <tbody>
          <tr>
            <td>I am the boss</td>
            <td>No, da-da is not the boss!</td>
            <td>Alexis, I am the boss, right?</td>
          </tr>
       </tbody>
    </table>
</div>

Then style the second table's parent to allow vertical scroll, in your CSS

    .table-content-class {
        overflow-y: scroll;    // use auto; or scroll; to allow vertical scrolling; 
        overflow-x: hidden;    // disable horizontal scroll 
    }

You have to insert your <table> into a <div> that it has fixed size, and in <div> style you have to set overflow: scroll.


Worth noting, that depending on your purpose (mine was the autofill results of a searchbar) you may want the height to be changeable, and for the scrollbar to only exist if the height exceeds that.

If you want that, replace height: x; with max-height: x;, and overflow:scroll with overflow:auto.

Additionally, you can use overflow-x and overflow-y if you want, and obviously the same thing works horizontally with width : x;


Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to scroll

How to window.scrollTo() with a smooth effect Angular 2 Scroll to bottom (Chat style) Scroll to the top of the page after render in react.js Get div's offsetTop positions in React RecyclerView - How to smooth scroll to top of item on a certain position? Detecting scroll direction How to disable RecyclerView scrolling? How can I scroll a div to be visible in ReactJS? Make a nav bar stick Disable Scrolling on Body

Examples related to html-table

Table column sizing DataTables: Cannot read property 'length' of undefined TypeError: a bytes-like object is required, not 'str' in python and CSV How to get the <td> in HTML tables to fit content, and let a specific <td> fill in the rest How to stick table header(thead) on top while scrolling down the table rows with fixed header(navbar) in bootstrap 3? Sorting table rows according to table header column using javascript or jquery How to make background of table cell transparent How to auto adjust table td width from the content bootstrap responsive table content wrapping How to print table using Javascript?

Examples related to overflow

Bootstrap button drop-down inside responsive table not visible because of scroll Remove scrollbars from textarea Carry Flag, Auxiliary Flag and Overflow Flag in Assembly Horizontal scroll css? Body set to overflow-y:hidden but page is still scrollable in Chrome How can I add a vertical scrollbar to my div automatically? CSS text-overflow: ellipsis; not working? Have a fixed position div that needs to scroll if content overflows Mobile overflow:scroll and overflow-scrolling: touch // prevent viewport "bounce" Overflow-x:hidden doesn't prevent content from overflowing in mobile browsers