53

I want to do this as easily as possible with out any additional libraries.

In my very long table I want to add a scrollbar to the <tbody> tag so that the head is always visible but it wont work. can you please help.

fiddle : http://jsfiddle.net/Hpx4L/

<table border="1">
  <thead>
    <tr>
      <th>Month</th>
      <th>Savings</th>
    </tr>
  </thead>
  <tfoot>
    <tr>
      <td>Sum</td>
      <td>$180</td>
    </tr>
  </tfoot>
  <tbody style="overflow-y:scroll; height:100px;"> <!-- wont work -->
    <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
          <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>$80</td>
    </tr>
  </tbody>
</table>
Hello-World
  • 9,277
  • 23
  • 88
  • 154

4 Answers4

86

you can wrap the content of the <tbody> in a scrollable <div> :

html

....
<tbody>
  <tr>
    <td colspan="2">
      <div class="scrollit">
        <table>
          <tr>
            <td>January</td>
            <td>$100</td>
          </tr>
          <tr>
            <td>February</td>
            <td>$80</td>
          </tr>
          <tr>
            <td>January</td>
            <td>$100</td>
          </tr>
          <tr>
            <td>February</td>
            <td>$80</td>
          </tr>
          ...

css

.scrollit {
    overflow:scroll;
    height:100px;
}

see my jsfiddle, forked from yours: http://jsfiddle.net/VTNax/2/

braican
  • 2,172
  • 1
  • 18
  • 16
  • 2
    I can't believe I wasted hours trying to fix my broken layout as a result of using ``, when the solution was as simple as putting `` inside a scrollable `
    `. Thanks for your solution!
    – Nolonar Jan 22 '14 at 16:57
  • @braican Doesn't seem to work for me, can you take a look please. – Shan Nov 21 '14 at 11:21
  • I seem to have alignment issues – myol Feb 12 '16 at 11:43
  • How does this accomodate for different browser sizes? – sparkyShorts Mar 17 '16 at 21:00
  • 1
    @myol because the inner table is independent of the outer table, you may need to set an explicit width for the appropriate columns. You'll notice in my jsfiddle that the first element in both the parent and child tables have a width of 200 set. Unfortunately, since the two tables aren't technically related at all, this is the most foolproof way to ensure the columns match up. – braican Mar 21 '16 at 13:50
  • 1
    @sparkyShorts there shouldn't be any issues with different browser sizes (though I'd imagine some work would be needed at the phone size). Assuming your tables are set up to respond to differing browser sizes, everything should cascade appropriately. – braican Mar 21 '16 at 13:52
  • 3
    `table > div > tbody` is invalid HTML syntax – oluckyman Jul 25 '16 at 10:30
  • 1
    How does this affect accessibility? – RON2015 Dec 14 '18 at 19:09
  • 1
    This is no longer a semantically correct table and if that's the case you shouldn't bother using tables at all – Pete Mar 20 '20 at 11:50
16

These solutions often have issues with the header columns aligning with the body columns, and may not work properly when resizing. I know you didn't want to use an additional library, but if you happen to be using jQuery, this one is really small. It supports fixed header, footer, column spanning (colspan), horizontal scrolling, resizing, and an optional number of rows to display before scrolling starts.

jQuery.scrollTableBody (GitHub)

As long as you have a table with proper <thead>, <tbody>, and (optional) <tfoot>, all you need to do is this:

$('table').scrollTableBody();
Noah Heldman
  • 6,724
  • 3
  • 40
  • 40
  • 1
    This is the only solution I could find that did not require screwing up the HTML/CSS of the table. Thanks! – Sevin7 Apr 23 '14 at 10:15
  • 11
    @Sevin7 If you look at the code for this jQuery plugin, it is actually adding extra html / css to your table. So it's screwing up the html / css for you, rather than you having to do it yourself. – Giles Roberts Apr 28 '14 at 12:56
6

This is because you are adding your <tbody> tag before <td> in table you cannot print any data without <td>.

So for that you have to make a <div> say #header with position: fixed;

 header
 {
      position: fixed;
 }

make another <div> which will act as <tbody>

tbody
{
    overflow:scroll;
}

Now your header is fixed and the body will scroll. And the header will remain there.

Veer Shrivastav
  • 5,434
  • 11
  • 53
  • 83
-1

If you don't want to wrap a table under any div:

table{
  table-layout: fixed;
}
tbody{
      display: block;
    overflow: auto;
}
GorvGoyl
  • 42,508
  • 29
  • 229
  • 225