How to specify table's height such that a vertical scroll bar appears?
Asked Answered
L

5

126

I have a table with many rows on my page. I would like to set table's height, say for 500px, such that if the height of the table is bigger than that, a vertical scroll bar will appear. I tried to use CSS height attribute on the table, but it doesn't work.

Litchi answered 16/12, 2010 at 3:52 Comment(3)
Maybe use max-height instead of just height as the latter will force the table's height to be 500pxSogdian
You may want to ask a second question, about keeping the header row from scrolling. ;)Tripartite
See also #1588427Utilitarianism
C
213

Try using the overflow CSS property. There are also separate properties to define the behaviour of just horizontal overflow (overflow-x) and vertical overflow (overflow-y).

Since you only want the vertical scroll, try this:

table {
  height: 500px;
  overflow-y: scroll;
}

EDIT:

Apparently <table> elements don't respect the overflow property. This appears to be because <table> elements are not rendered as display: block by default (they actually have their own display type). You can force the overflow property to work by setting the <table> element to be a block type:

table {
  display: block;
  height: 500px;
  overflow-y: scroll;
}

Note that this will cause the element to have 100% width, so if you don't want it to take up the entire horizontal width of the containing element, you need to specify an explicit width for the element as well.

Cooee answered 16/12, 2010 at 3:55 Comment(9)
This doesn't limit the height though.Sogdian
@Fred: I thought it was implied, but you're right. I've added an explicit height property to my example.Cooee
No, it does, you just need display:block on the table to make it behave like a div jsfiddle.net/TSGSA/1Sogdian
@Misha: This seems to be because tables arent block elements. See my edit.Cooee
This answer really helped me, but instead of applying it to the table tag, it should be done to the tbody, in order to allow the header to remain static when scrolling. Then there's some styling to sort out with regard to the area in the thead that is above the scroll bar.Lieb
@Derek - I know this is incredibly late, but I just saw this (got some rep on it and remembered it existed). It looks like you can fix this by setting the CSS on the tbody and including position:absolute (you may need to set the table element itself to position:relative to anchor the tbody so it doesn't get rendered in a weird spot). It looks like you'll need to explicitly set the width to 100% to match the original answer. I just played with this for like 5 minutes in an IETester (IE9 only), so it may not be complete and it may not work correctly on actual IE9 or at all on IE8.Cooee
@Derek Here's the updated fiddle. Let me know if it works and I'll update the answer. I'll try to test it properly tomorrow. jsfiddle.net/TSGSA/113Cooee
If you're going to use this on the tbody, make sure you add the display:block to the thead (and probably tfoot) or they could go a little crazy. The problem, it seems, is that once you do this, you've broken the link between the thead and tbody: columns of the former aren't aware of the width of the latter. So you patch that and down the slippery slope you go. "I died for beauty..."Subcritical
For some reason Chrome needs a <!doctype html>, or it ignores the overflow.Chaldean
G
74

You need to wrap the table inside another element and set the height of that element. Example with inline css:

<div style="height: 500px; overflow: auto;">
 <table>
 </table>
</div>
Gould answered 16/12, 2010 at 3:54 Comment(8)
This won't allow for keeping the thead in place while the tbody scrolls.Lieb
This requirement is not in the original question.Gould
Also, the other (accepted) answer doesn't keep the thead in place either.Asterism
You can still make there appear to be a header in place with this method. You hide the table's header, then create a second table above the first table that has the header in it. Then, style both tables to have display:table; their rows to have display:table-row; and their cells to have display:table-cell; and the two tables will match up and appear to be one. (NOTE: this doesn't work with very large tables; basically, it matches them up when it can. I've used this technique multiple times.)Collettecolletti
Is there a way to do this with percentage height? I don't want to use a fixed pixel height when the rest of the page is responsive, but this method only seems to work with fixed height. I've specified the maximum height of each TD and TR in pixels in an attempt to remove any circular dependency in size calculation but still no joy.Degrade
Sure. The parent's size must be specified to use relative sizes. For example: jsfiddle.net/hz8wyGould
@DarkFalcon: Thanks! Does this mean everything going back to the root element (the <HTML> tag) must have a manually specified "height=100%", for example? I tried this and it indeed limits the table size -- in fact it squashed it into a tiny scrollable box, perhaps because I had left things like "height=4%" in various DIVs for testing and forgot about them because they had no effect. Hopefully we can force a percentage size for the table (or its parent div) without having to restrict and specify the sizes of all ancestors as that would be cumbersome :DDegrade
Yes, to my knowledge any element which uses a relative size must have a parent which has an explicit size specified. If that parent is relative-sized, its parent must also have a size, all the way up to the html element. For practical purposes, the html element's parent can be considered to be the window, which has a non-relative size.Gould
F
12

None of those solutions worked. However, I grabbed the flex solution of Bootstrap and it worked

table, td {
  border: 1px solid black;
}
th {
  border-left: 1px solid black;
}

table {
  border-collapse: collapse;
  width: 100%;
}

table {
    display: flex;
    flex-flow: column;
    width: 100%;
    height: 400px;
    
}

thead {
    padding-right: 13px;
    flex: 0 0 auto;
}

tbody {
    flex: 1 1 auto;
    display: block;
    overflow-y: auto;
    overflow-x: hidden;
}

tr {
    width: 100%;
    display: table;
    table-layout: fixed;
}
<table>
<thead>
  <tr>
    <th>Firstname</th>
    <th>Lastname</th>
    <th>Savings</th>
  </tr>
  </thead>
  <tbody>
  <tr>
    <td>Peter</td>
    <td>Griffin</td>
    <td>$100</td>
  </tr>
  <tr>
    <td>Lois</td>
    <td>Griffin</td>
    <td>$150</td>
  </tr>
  <tr>
    <td>Joe</td>
    <td>Swanson</td>
    <td>$300</td>
  </tr>
  <tr>
    <td>Cleveland</td>
    <td>Brown</td>
    <td>$250</td>
  </tr>
    <tr>
    <td>Peter</td>
    <td>Griffin</td>
    <td>$100</td>
  </tr>
  <tr>
    <td>Lois</td>
    <td>Griffin</td>
    <td>$150</td>
  </tr>
  <tr>
    <td>Joe</td>
    <td>Swanson</td>
    <td>$300</td>
  </tr>
  <tr>
    <td>Cleveland</td>
    <td>Brown</td>
    <td>$250</td>
  </tr>
    <tr>
    <td>Peter</td>
    <td>Griffin</td>
    <td>$100</td>
  </tr>
  <tr>
    <td>Lois</td>
    <td>Griffin</td>
    <td>$150</td>
  </tr>
  <tr>
    <td>Joe</td>
    <td>Swanson</td>
    <td>$300</td>
  </tr>
  <tr>
    <td>Cleveland</td>
    <td>Brown</td>
    <td>$250</td>
  </tr>
    <tr>
    <td>Peter</td>
    <td>Griffin</td>
    <td>$100</td>
  </tr>
  <tr>
    <td>Lois</td>
    <td>Griffin</td>
    <td>$150</td>
  </tr>
  <tr>
    <td>Joe</td>
    <td>Swanson</td>
    <td>$300</td>
  </tr>
  <tr>
    <td>Cleveland</td>
    <td>Brown</td>
    <td>$250</td>
  </tr>
    <tr>
    <td>Peter</td>
    <td>Griffin</td>
    <td>$100</td>
  </tr>
  <tr>
    <td>Lois</td>
    <td>Griffin</td>
    <td>$150</td>
  </tr>
  <tr>
    <td>Joe</td>
    <td>Swanson</td>
    <td>$300</td>
  </tr>
  <tr>
    <td>Cleveland</td>
    <td>Brown</td>
    <td>$250</td>
  </tr>
    <tr>
    <td>Peter</td>
    <td>Griffin</td>
    <td>$100</td>
  </tr>
  <tr>
    <td>Lois</td>
    <td>Griffin</td>
    <td>$150</td>
  </tr>
  <tr>
    <td>Joe</td>
    <td>Swanson</td>
    <td>$300</td>
  </tr>
  <tr>
    <td>Cleveland</td>
    <td>Brown</td>
    <td>$250</td>
  </tr>
    <tr>
    <td>Peter</td>
    <td>Griffin</td>
    <td>$100</td>
  </tr>
  <tr>
    <td>Lois</td>
    <td>Griffin</td>
    <td>$150</td>
  </tr>
  <tr>
    <td>Joe</td>
    <td>Swanson</td>
    <td>$300</td>
  </tr>
  <tr>
    <td>Cleveland</td>
    <td>Brown</td>
    <td>$250</td>
  </tr>
  </tbody>
</table>
Fortepiano answered 11/4, 2022 at 13:53 Comment(2)
All other solutions broke the width of the table but this one worksSaponaceous
This is the only solution that retains the tables layout - should be the accepted answerMonadelphous
V
4

This CSS also shows a fixed height HTML table. It sets the height of the HTML tbody to 400 pixels and the HTML tbody scrolls when the it is larger, retaining the HTML thead as a non-scrolling element.

In addition, each th cell in the heading and each td cell the body should be styled for the desired fixed width.

#the-table {
  display: block;
  background: white; /* optional */
}

#the-table thead {
  text-align: left; /* optional */
}

#the-table tbody {
  display: block;
  max-height: 400px;
  overflow-y: scroll;
}
Vignola answered 3/2, 2021 at 5:47 Comment(1)
This obviously disconnects the tbody from the rest of the table, resulting in header (and footer) cells not being aligned with the cells of the body width wise. I would call this approach flawed, unless you address the alignment of the columns somehow (maybe javascript?).Pfister
B
1

to set the height of table, you need to first set css property "display: block" then you can add "width/height" properties. I find this Mozilla Article a very good resource to learn how to style tables : Link

Bushmaster answered 16/7, 2018 at 9:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.