3

I have a table with dynamically generated data. Because of space limitation, I need to be able to make the the tbody scrollable.

My table looks like this:

<table>
    <thead> <! -- This thead needs to stay in a fixed position-->
        <tr>
               <th></th>
               <th></th>
        </tr>
    <thead>
    <tbody> <! -- This tbody needs to stay in a fixed position-->
     <tr>
      <td></td>
      <td></td>
     </tr>
   </tbody>
   <tbody> <! -- This tbody needs to scroll -->
     <tr>
      <td></td>
      <td></td>
     </tr>
     </tbody>
</table>

I've tried using css, but have been unsuccessful:

table tbody:nth-child(2) {
height:500px;
max-height:500px;
overflow-y: scroll;
}

My ideal solution is simple css. Any suggestions? Also, why does setting a height on a tbody not work?

Mark
  • 4,773
  • 8
  • 53
  • 91

2 Answers2

3

You can make the tbody scrollable by doing the below:

tbody { 
    display: block; /* mandatory because scroll only works on block elements */
}

tbody:nth-child(3) {
    height: 75px;       /* Just for the demo          */
    overflow-y: auto;    /* Trigger vertical scroll    */
    width: 100px;       /* Just for the demo          */ 
}

Demo | Demo with Class Name

Note: If you wish you can either target the tbody as mentioned in the above sample or much better would be assigning it a scrollable class and doing as below:

tbody.scrollable {
    height: 75px;       /* Just for the demo          */
    overflow-y: auto;    /* Trigger vertical scroll    */
    width: 100px;       /* Just for the demo          */ 
}

Base Idea: Base Idea is taken from Hashem's answer in this thread.

Update: The tbody:nth-child(2) didn't work because that selector applies the style to the 2nd child element which is also a tbody. In our case, it worked but it didn't have any effect because the 2nd child within the table was the first tbody (after the thead) and it had lesser contents which made the scrollbar unnecessary. When we made it to nth-child(3), it worked because the 2nd tbody is actually the 3rd child element and had enough contents to exceed the set height and thereby triggered the scrollbar to come.

Have a look at this sample for reference. We can see that the style is not applied for the 1st element in the 2nd div and the 2nd element in the 1st div because both of them are not p tags (even though the CSS rule was same for both divs).

Community
  • 1
  • 1
Harry
  • 87,580
  • 25
  • 202
  • 214
  • 1
    Harry, this works in your demo, but when I update it with my table, this doe not work. http://jsfiddle.net/guT8P/5/ – Mark Jul 11 '14 at 14:17
  • 1
    Ah, you took the example that I was updating at the wrong time. For that sample which uses `tbody.second`, you need to assign the `class='second'` to the corresponding `tbody` like ``. Or better still a semantical and re-usable class name would be `scrollable`. – Harry Jul 11 '14 at 14:19
  • I cant believe I did that, haha I thought .second was some new selector. duh – Mark Jul 11 '14 at 14:22
  • 1
    Happens to the best of us too mate. By the way, have a look at [this SO thread](http://stackoverflow.com/questions/17067294/html-table-with-100-width-with-vertical-scroll-inside-tbody) for some alternates. – Harry Jul 11 '14 at 14:23
  • 1
    The `nth-child` didn't work probably because both of us overlooked the fact that the `tbody` that we were looking to scroll is actually the 3rd child within the table and not the 2nd. Refer [this sample](http://jsfiddle.net/hari_shanx/th7sj/) and see that 1st child doesn't get the style because it is not a `p` element (it is a `h1`). – Harry Jul 11 '14 at 14:41
  • This does not work once you don't use 'a' as header and footer: once you set display: block on tbody/thead the column widths don't match up anymore. – Mrten Feb 17 '18 at 17:53
0

Try below approach simple easy to implement

below is the jsfiddle link

http://jsfiddle.net/v2t2k8ke/2/

HTML:

<table border='1' id='tbl_cnt'>
<thead><tr></tr></thead><tbody></tbody>

CSS:

 #tbl_cnt{
 border-collapse: collapse; width: 100%;word-break:break-all;
 }
 #tbl_cnt thead, #tbl_cnt tbody{
 display: block;
 }
 #tbl_cnt thead tr{
 background-color: #8C8787; text-align: center;width:100%;display:block;
 }
 #tbl_cnt tbody {
 height: 100px;overflow-y: auto;overflow-x: hidden;
 }

Jquery:

 var data = [
    {
    "status":"moving","vehno":"tr544","loc":"bng","dri":"ttt"
    }, {
    "status":"stop","vehno":"tr54","loc":"che", "dri":"ttt"
    },{    "status":"idle","vehno":"yy5499999999999994","loc":"bng","dri":"ttt"
    },{
    "status":"moving","vehno":"tr544","loc":"bng", "dri":"ttt"
    }, {
    "status":"stop","vehno":"tr54","loc":"che","dri":"ttt"
    },{
    "status":"idle","vehno":"yy544","loc":"bng","dri":"ttt"
    }
    ];
   var sth = '';
   $.each(data[0], function (key, value) {
     sth += '<td>' + key + '</td>';
   });
   var stb = '';        
   $.each(data, function (key, value) {
       stb += '<tr>';
       $.each(value, function (key, value) {
       stb += '<td>' + value + '</td>';
       });
       stb += '</tr>';
    });
      $('#tbl_cnt thead tr').append(sth);
      $('#tbl_cnt tbody').append(stb);
      setTimeout(function () {
      var col_cnt=0 
      $.each(data[0], function (key, value) {col_cnt++;});    
      $('#tbl_cnt thead tr').css('width', ($("#tbl_cnt tbody") [0].scrollWidth)+ 'px');
      $('#tbl_cnt thead tr td,#tbl_cnt tbody tr td').css('width',  ($('#tbl_cnt thead tr ').width()/Number(col_cnt)) + 'px');}, 100)
Nandha
  • 655
  • 1
  • 6
  • 14