Setting a max height on a table
Asked Answered
E

12

76

I am trying to design a page where there are some tables. It seems that styling tables is much more painful than it ought to be.

The problem is the following: The tables should have a fixed height and display either white space at the bottom (when there is too little content) or a vertical scrollbar (when there is too much). Add to this that the tables have a header which should not scroll.

As far as I know, the thead not scrolling is the default behaviour for tables. And a stretching tfoot could serve well for the purpose of filling with white space. Sadly, it seems that every constraint I can put on the table height is cheerfully ignored. I have tried

table {
    height: 600px;
    overflow: scroll;
}

I have tried with max-height. I have tried to position the table absolutely and give both the top and bottom coordinates. I have tried to manually edit the height in Firebug to see if it was a problem with CSS specificity. I have tried to set the height on the tbody too. Fact is, the table always stays exactly the same height as its content, regardless of my efforts.

Of course I could fake a table with a div structure, but it actually is a table, and I fear using divs I may run into an issue where some columns may not be properly aligned.

How am I supposed to give a table a height?

Essive answered 23/1, 2012 at 10:42 Comment(3)
See also I need my html table's body to scroll and its head to stay put and my answer, which I believe solves the problem.Skylar
To others looking for an AWESOME answer to this question, check out Sibi John's answer below: https://mcmap.net/q/269103/-setting-a-max-height-on-a-tableCallao
HTML sucks, there are only workaround. For this case, a viable workaround is to enhost the table into a DIV and setting the height-overflow attributes to it. Add padding: 1px to avoid yet another scroll bugKirstiekirstin
S
31

NOTE this answer is now incorrect. I may get back to it at a later time.

As others have pointed out, you can't set the height of a table unless you set its display to block, but then you get a scrolling header. So what you're looking for is to set the height and display:block on the tbody alone:

<table style="border: 1px solid red">
    <thead>
        <tr>
            <td>Header stays put, no scrolling</td>
        </tr>
    </thead>
    <tbody style="display: block; border: 1px solid green; height: 30px; overflow-y: scroll">
        <tr>
            <td>cell 1/1</td>
            <td>cell 1/2</td>
        </tr>
        <tr>
            <td>cell 2/1</td>
            <td>cell 2/2</td>
        </tr>
        <tr>
            <td>cell 3/1</td>
            <td>cell 3/2</td>
        </tr>
    </tbody>
</table>

Here's the fiddle.

Skylar answered 30/10, 2012 at 0:23 Comment(7)
Thank you, tour solution seems to work exactly as I wanted. I do not know why someone downvoted your answerEssive
Unfortunately, this causes the body's columns to no longer align with the header's columns: jsfiddle.net/JPGEk/15Moresque
Hate to downvote, but as @Moresque Mintern mentioned, this answer is incorrectRauwolfia
@user1749204: thanks, I've added a comment at the top. Would downvote it myself if I could.Skylar
Don't state that this is incorrect and you might improve it later, delete the answer instead. Then, if you decide to revisit it, you can always undelete it.Casandracasanova
Please don't delete it, the answer is still partially correct, I was able to use this code and align the header manually with display block and a defined px width.Myra
Answer is a little correct but at this point displaying a table as a block destroys the column and row semantics. You should wrap the table in a div and set the max height and overflow-y settings on that div. Not sure how to make the table headers sticky though.Och
D
31
  • Set display: block; for the table
  • Set position: sticky; top: 0; for the header row
<table style="display: block; height: 100px; overflow: auto;">
  <thead>
    <tr>
      <td style="position: sticky; top: 0;">Header stays put</td>
      <td style="position: sticky; top: 0;">Layout aligned</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>foo1</td>
      <td>Header stays put</td>
    </tr>
    <tr>
      <td>foo2</td>
      <td>Header stays put</td>
    </tr>
  </tbody>
</table>

https://jsfiddle.net/0zxk18fp/

Tested on Chrome, Firefox, Safari, Edge

Determiner answered 10/4, 2020 at 18:47 Comment(4)
This seems like by far the best and simplest. I had no issues other than I also had to add z-index to the table header to prevent table contents from overlapping it when scrolling.Kittykitwe
@Kittykitwe can you share your code? i'm playng with the z-index and it's not helping meVarian
I just added background-color: white; to the td style.Fulfill
The width of thead and tbody don't occupy the remaining width of the table unless the content is big enough. Otherwise, this is the best solution I've seen yet that doesn't require a separate table and some Javascript.Testes
L
10

Add display:block; to the table's css. (in other words.. tell the table to act like a block element rather than a table.)

fiddle here

Left answered 23/1, 2012 at 10:48 Comment(2)
Thank you. This seems to work partially. The only problem that remains is that now the thead scrolls together with the table, while it should stay fixed. I am pretty sure I have seen examples where the body of the table scrolls, but I cannot reproduce it. :-(Essive
This accepted answer only solved the problem partially. For a complete solution, please see this answerSkylar
C
6

A simple workaround that is available in most of the cases it to wrap the table in a div and then give a max-height to that div:

.scrollable-wrapper {
  max-height: 400px;
  overflow: auto;
}

/* Add also the following code if sticky header is wanted */
.scrollable-wrapper table thead th {
  background: #afa;
  position: sticky;
  top: 0;
  box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.4);
}

<div class="scrollable-wrapper">
  <table>
    <thead>
      <tr>
        <th>Id</th>
        <th>Text</th>
      </tr>
    </thead>
    <tbody></tbody>
  </table>
</div>

Codepen: https://codepen.io/Conejoo/pen/NWpjmYw

Cho answered 25/5, 2021 at 3:51 Comment(2)
This should be marked as answer!!!Birthstone
The downside with this solution is the vertical scrollbar starts from the header of the table not the body of the table. This is not appealing to users.Garderobe
A
5

You can do this by using the following css.

.scroll-thead{
    width: 100%;
    display: inline-table;
}

.scroll-tbody-y
{
    display: block;
    overflow-y: scroll;
}

.table-body{
    height: /*fix height here*/;
}

Following is the HTML.

<table>
 <thead class="scroll-thead">
          <tr> 
           <th>Key</th>
           <th>Value</th>
          </tr> 
         </thead>
         <tbody class="scroll-tbody-y table-body">
          <tr> 
          <td>Blah</td> 
          <td>Blah</td> 
          </tr> 
</tbody>
</table>

JSFiddle

Appointment answered 8/2, 2017 at 11:46 Comment(1)
your column headers don't stay inline with your content. IE, make your "keys" header say "keys keys keys keys" instead of just "keys" and they won't line up.Doorn
N
3

I had a coworker ask how to do this today, and this is what I came up with. I don't love it but it is a way to do it without js and have headers respected. The main drawback however is you lose some semantics due to not having a true table header anymore.

Basically I wrap a table within a table, and use a div as the scroll container by giving it a max-height. Since I wrap the table in a parent table "colspanning" the fake header rows it appears as if the table respects them, but in reality the child table just has the same number of rows.

One small issue due to the scroll bar taking up space the child table column widths wont match up exactly.

Live Demo

Markup

<table class="table-container">
    <tbody>
        <tr>
            <td>header col 1</td>
            <td>header col 2</td>
        </tr>
        <tr>
            <td colspan="2">
                <div class="scroll-container">
                    <table>
                        <tr>
                            <td>entry1</td>
                            <td>entry1</td>
                        </tr>
                       ........ all your entries
                    </table>
                </div>
            </td>
        </tr>
    </tbody>
</table>

CSS

.table-container {
    border:1px solid #ccc;
    border-radius: 3px;
    width:50%;
}
.table-container table {
    width: 100%;
}
.scroll-container{
    max-height: 150px;
    overflow-y: scroll;
}
Nilla answered 2/10, 2014 at 18:41 Comment(4)
This solution does not work properly. Columns of header are not aligned with the body columns at all. In the provided example it looks OK just by coincidence, because header text of each column has equal length and so do body cell contents. It's not only matter of scroll. Please see this forked fiddle where I've only modified text in header and body.Adelladella
@Nilla - Hardcoding columns width is good if it contains static content that you know up front, but with dynamic content I would rather like the columns to adjust proportionally to content, like in a plain table.Adelladella
@Adelladella Yeah I agree you would have to handle it on a case per case basis. haha like I say in my answer I don't love it but we had a no js constraint for this particular bit so it was the best solution I could come up with :PNilla
Fair enough. The great advantage of your solution is that it doesn't need js. I just wanted to share my observation, to make it clear for the future readers about the limitations.Adelladella
R
2

Seems very similar to this question. From there it seems that this should do the trick:

table {
  display: block; /* important */
  height: 600px;
  overflow-y: scroll;
}
Roundelay answered 23/1, 2012 at 10:49 Comment(2)
Thank you. This seems to work partially. The only problem that remains is that now the thead scrolls together with the table, while it should stay fixed. I am pretty sure I have seen examples where the body of the table scrolls, but I cannot reproduce it. :-(Essive
Hate to downvote, but as @Essive mentioned, this answer is incorrect.Skylar
L
1

In Tables, For minimum table cells height or rows height use css height: in place of min-height:

AND

For Limiting max-height of all cells or rows in table with Javascript:

This script is good for horizontal overflow tables.

This script increase the table width 300px each time (maximum 4000px) until rows shrinks to max-height(160px) , and you can also edit numbers as your need.

var i = 0, row, table = document.getElementsByTagName('table')[0], j = table.offsetWidth;
while (row = table.rows[i++]) {
    while (row.offsetHeight > 160 && j < 4000) {
        j += 300;
        table.style.width = j + 'px';
    }
}

Source: HTML Table Solution Max Height Limit For Rows Or Cells By Increasing Table Width, Javascript

Lubow answered 11/8, 2015 at 2:57 Comment(0)
I
1

Use divs with max height and min height around the content that needs to scroll.

<tr>
    <td>
        <div>content</div>
    </td>
</tr>

td div{
    max-height:20px;
}

https://jsfiddle.net/ethanabrace/4w0ksczr/

Inconstant answered 10/1, 2018 at 11:34 Comment(2)
And what about the scrolling?Kentiggerma
Just add overflow-y:scroll; to the td div{} css - updated fiddle to reflectInconstant
H
0

Just try this.

<div style="max-height: 400px; overflow: scroll">

    <!--This is your table-->
    <table style="border: 1px solid red">
        <thead>
            <tr>
                <td>Header stays put, no scrolling</td>
            </tr>
        </thead>
        <tbody style="display: block; border: 1px solid green; height: 30px; overflow-y: scroll">
            <tr>
                <td>cell 1/1</td>
                <td>cell 1/2</td>
            </tr>
            <tr>
                <td>cell 2/1</td>
                <td>cell 2/2</td>
            </tr>
            <tr>
                <td>cell 3/1</td>
                <td>cell 3/2</td>
            </tr>
        </tbody>
    </table>


</div>
Harville answered 10/1, 2023 at 23:16 Comment(0)
L
0

116 Version later.

Html

<div style="background:green;height:40px;width:100%;display:block;">Test Div</div>
<div class="grid-table">
  <div class="grid-row table-head">
    <div>Header 1</div>
    <div>Header 2</div>
    <div>Header 3</div>
  </div>
  <div class="grid-row">
    <div>Row 1, Cell 1</div>
    <div>Row 1, Cell 2dddddddddddddddddddddddhjbuozgbozugbouzbuozbozubozubuozbuozboudddddddddddddddddddddddddd</div>
    <div>Row 1, Cell jjjjjikniuhjiuhjuihuihuihuihiu3</div>
  </div>
<!-- Add more here -->
</div>

CSS

.grid-table {
    display: grid;
    grid-template-columns: repeat(3, minmax(min-content, 1fr));
    grid-auto-rows: auto;
    width: 100%;
    border-collapse: collapse;
        height:300px;
        overflow:auto;
  }

  .grid-row {
    display: contents;
  }

  .grid-row > div {
    padding: 10px;
    border: 1px solid #ccc;
        word-break: break-all;
  }
    
  .grid-row:first-child > div {
    background-color:darkgreen;
        color:white;
  }
    
    .table-head > div {
        position:sticky;
        top:0;
    }

Feel free to add many entrys as you want.

JSFiddle

Lubumbashi answered 28/3, 2023 at 17:48 Comment(0)
K
-1
<table  style="border: 1px solid red">
            <thead>
                <tr>
                    <td>Header stays put, no scrolling</td>
                </tr>
            </thead>
            <tbody id="tbodyMain" style="display: block; border: 1px solid green; height: 30px; overflow-y: scroll">
                <tr>
                    <td>cell 1/1</td>
                    <td>cell 1/2</td>
                </tr>
                <tr>
                    <td>cell 2/1</td>
                    <td>cell 2/2</td>
                </tr>
                <tr>
                    <td>cell 3/1</td>
                    <td>cell 3/2</td>
                </tr>
            </tbody>
        </table>


Javascript Section

<script>
$(document).ready(function(){
   var maxHeight = Math.max.apply(null, $("body").map(function () { return $(this).height(); }).get());
   // alert(maxHeight);
    var borderheight =3 ; 
    // Added some pixed into maxheight 
    // If you set border then need to add this "borderheight" to maxheight varialbe
   $("#tbodyMain").css("min-height", parseInt(maxHeight + borderheight) + "px");             
});

</script>


please, refer How to set maximum possible height to your Table Body
Fiddle Here

Kenlay answered 15/4, 2013 at 9:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.