CSS3 Display:Table, Overflow-Y:Scroll Doesn't Work

CSS3 display:table, overflow-y:scroll doesn't work

  • It seems that if your display value is table, you cannot set a height or max-height

    Effectively, the spec says (max-height):

    In CSS 2.1, the effect of 'min-height' and 'max-height' on tables,
    inline tables, table cells, table rows, and row groups is undefined.

    And you can use the height property, but it will be treated as a minimum height, and thus won't produce overflow (Table height algorithms):

    The height of a table is given by the 'height' property for the
    'table' or 'inline-table' element. A value of 'auto' means that the
    height is the sum of the row heights plus any cell spacing or borders.
    Any other value is treated as a minimum height.

  • Also, if you remove the display:table from the parent but keep the display:table-row and table-cell, the width of the rows will not be 100%

    In this case, since there is no tabular container, an anonymous one is generated (Anonymous table objects):

    Document languages other than HTML may not contain all the elements in
    the CSS 2.1 table model. In these cases, the "missing" elements must
    be assumed in order for the table model to work. Any table element
    will automatically generate necessary anonymous table objects around
    itself

    But that anonymous table won't necessarily be as wide as .fake-table.

  • I tried instead doing this with flexbox

    Flexbox is a bad choice because it has no grid notion.

    Maybe CSS Grid would be better, but it's currently experimental and only IE10 supports it (an older version of the spec, tough).

Basically, you have two options:

  • Fixed column width approach

    If you predefine the width of the columns, the result will be a grid, even if you don't use tabular/grid displays.

  • Non-tabular to wrapper

    You can wrap your table inside a dummy (non-tabular) element, and set overflow and max-height to that element.

Table overflow scroll css doesn't work

Bug in your css:

tbody {
overflow-y scroll;
}

should be:

tbody {
overflow-y: scroll;
}

Solution to your problem: define your height directly at child and use display: block

   tbody {
overflow-y: scroll;
display: block;
height: 200px;
}

body {  background: #6CD3F8;  /*background: -webkit-linear-gradient(top left, #6CD3F8 0%, #E0F7FE 100%);  background: linear-gradient(to bottom right, #6CD3F8 0%, #E0F7FE 100%);*/}
h3 { color: white; text-align: left; margin-top: 20px;}
.scan { padding: 0% 10%;}
table { background: #E0F7FE; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px;}
table td,table td * { vertical-align: top;}
tbody { overflow-y: scroll; display: block; height: 200px;}
th { color: #265C82; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: normal; font-size: 17px; padding-left: 5px; padding-top: 5px;}
td { padding-left: 10px;}
::-webkit-input-placeholder { color: #00B2F3;}
.search { color: #00B2F3; border: 0px solid red; border-radius: 10px; width: calc(100% - 10px); height: 35px; margin-top: 5px}
.select { width: calc(100% - 10px);}
.icon { width: 20px; height: 20px; margin: 2px 8px 0px 5px; float: left;}
hr { border-color: #00B2F3; margin: 3px 0; width: calc(100% - 5px);}
.subjects { width: 100%; height: 200px;}
.classes { width: 100%; height: 200px; margin-top: 5px;}
.sections { width: 100%; height: 405px;}
.left { width: 50%; float: left; margin-right: 5px; margin-bottom: 3%; min-width: 300px;}
.right { width: calc(50% - 10px); float: left; min-width: 300px; margin-bottom: 3%;}
.mid { width: 100%; text-align: center; float: left; position: relative;}
.wrapper { width: 100%; text-align: right; float: left; position: relative;}
.logo { max-width: 30%; margin: 10px 0px;}
.links > a { color: rgba(255, 255, 255, 0.8); font-size: 16px; padding: 0px 10px;}
.links { /*padding-left: 100px;*/ padding-bottom: 10px;}
<body>
<div class="scan">
<h3>Summer Session A</h3>
<!-- <div class="left"> left </div> -->
<!-- <div class="right"> right </div> -->
<div class="left"> <table class="subjects"> <thead> <tr> <th> <div>Subject Areas</div> <hr> </th> </tr> <tr> <th> <input type="text" class="form-control search" onkeyup="searchFunction('subjects')" placeholder="Search..."> </th> </tr> </thead> <tbody> <tr> <td>Computer Science</td> </tr> <tr> <td>Mathematics</td> </tr> <tr> <td>Engineering</td> </tr> <tr> <td>Computer Science</td> </tr> <tr> <td>Mathematics</td> </tr> <tr> <td>Engineering</td> </tr> <tr> <td>Computer Science</td> </tr> <tr> <td>Mathematics</td> </tr> <tr> <td>Engineering</td> </tr> <tr> <td>Computer Science</td> </tr> <tr> <td>Mathematics</td> </tr> <tr> <td>Engineering</td> </tr> <!-- <select class="form-control" id="exampleSelect1"> <option>1</option> <option>2</option> <option>3</option> <option>4</option> <option>5</option> </select> --> <!-- <tr> <td> <select class="form-control select"> <option>1</option> <option>2</option> <option>3</option> <option>4</option> <option>5</option> </select> </td> </tr> -->
</tbody> </table>
<table class="classes"> <thead> <tr> <th> Classes <hr> </th> </tr> </thead> <tbody> <tr> <td></td> </tr> </tbody> </table> </div>
<div class="right"> <table class="sections"> <thead> <tr> <th> Overview <hr> </th> </tr> </thead> <tbody> <tr> <td></td> </tr> </tbody> </table> </div>
</div>

</body>

HTML table overflow not working

Your code is incorrect as you added an extra space between th and .t-Report-colHead in .t-Report-tableWrap table thead th .t-Report-colHead {

However, here is a working code.

tr{
display: table;
width: 100%;
table-layout: fixed;
}

thead{
display: block;
}

tbody{
display: block;
height: 180px;
overflow: auto;
}

CODEPEN

Hope this helps.

overflow-x is not working when the overflowing table is placed inside another table

First of all, div doesn't have width attribute.

Secondly, you have to specify the width, 100% of what? Now it is not known. Give a specific width to this div or to it's some parent.

Look into my snippet.

<html>    <body>        <table width="100%" >        <tbody>            <tr>                <td>                    <div style="overflow-x: scroll; overflow-y: scroll;width: 444px;" >                        <table>                            <tr>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                                <th> appleappleappleappleapple </th>                            </tr>                        </table>                    </div>                </td>            </tr>        </tbody>        </table>    </body></html>

Overflow doesn't work when using display:table-cell

I have used absolute positioning to try to fix your problem - fiddle here. Even when more lines of content are added, the height of the container will stay the same and a scrollbar will appear instead.

The CSS is simple:

#container {
width: 660px;
height: 375px;
position: relative;
background: #eee;
overflow: hidden;
}

#container .content {
width: 100%;
max-height: 100%;
position: absolute;
bottom: 0;
left: 0;
overflow: scroll;
}

The main container has a set height and hides any overflow. The content div inside is absolutely positioned to the bottom of this div and can never exceed the height of the main container. If it reaches 100% of the main container's height then a scrollbar will appear.

Try adding more content in and you'll see the scrollbar appear.

Vertical scroll not working for table

Try using the below code, this will introduce a vertical scroll in your code

.scroll {  height: 100px;  overflow-y: auto;}
<!DOCTYPE html><html lang="en">
<head> <meta charset="utf-8"> <title></title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css" rel="stylesheet"> <!-- Theme CSS --> <link href="css/style.css" rel="stylesheet"> <!-- Favicon --> <link rel="shortcut icon " href="img/favicon.ico "> <script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js "></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js "></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js "></script> <style type="text/css "> table { width: 800px; position: relative; } thead { display: block; overflow-y: auto; height: 30px; max-width: 100%; top: 0; font-size: 12px; } tbody { max-width: 100%; position: absolute; top: 40px; height: 2em; overflow-y: scroll; display: block; font-size: 10px; } table { width: 100%; /* Optional */ /* border-collapse: collapse; */ border-spacing: 0; border: 2px solid black; } table tbody, table thead { display: block; } </style></head><div class="container "> <div class="scroll"> <table class=" table table-bordered "> <thead> <tr> <th style="width: 2.5%;font-size: 12px; ">Sl No</th> <th style="width: 3%;font-size: 12px; ">First Name</th> <th style="width: 10%;font-size: 12px; ">Middle Name</th> <th style="width: 10%;font-size: 12px; ">Last Name</th> <th style="width: 10%;font-size: 12px; ">Email</th> <th style="width: 10%;font-size: 12px; ">Department</th> </tr> </thead> <tbody> <tr> <td style="font-size: 11px; ">1</td> <td style="font-size: 11px; ">User</td> <td style="font-size: 11px; ">Name</td> <td style="font-size: 11px;">Unknown</td> <td style="font-size: 11px; ">username@gmail.com</td> <td style="font-size: 11px; ">IT Development</td> </tr> <tr> <td style="font-size: 11px; ">12</td> <td style="font-size: 11px; ">User</td> <td style="font-size: 11px; ">Name</td> <td style="font-size: 11px;">Unknown</td> <td style="font-size: 11px; ">username@gmail.com</td> <td style="font-size: 11px; ">IT Development</td> </tr> <tr> <td style="font-size: 11px; ">3</td> <td style="font-size: 11px; ">User</td> <td style="font-size: 11px; ">Name</td> <td style="font-size: 11px;">Unknown</td> <td style="font-size: 11px; ">username@gmail.com</td> <td style="font-size: 11px; ">IT Development</td> </tr> <tr> <td style="font-size: 11px; ">4</td> <td style="font-size: 11px; ">User</td> <td style="font-size: 11px; ">Name</td> <td style="font-size: 11px;">Unknown</td> <td style="font-size: 11px; ">username@gmail.com</td> <td style="font-size: 11px; ">IT Development</td> </tr> <tr> <td style="font-size: 11px; ">5</td> <td style="font-size: 11px; ">User</td> <td style="font-size: 11px; ">Name</td> <td style="font-size: 11px;">Unknown</td> <td style="font-size: 11px; ">username@gmail.com</td> <td style="font-size: 11px; ">IT Development</td> </tr> <tr> <td style="font-size: 11px; ">6</td> <td style="font-size: 11px; ">User</td> <td style="font-size: 11px; ">Name</td> <td style="font-size: 11px;">Unknown</td> <td style="font-size: 11px; ">username@gmail.com</td> <td style="font-size: 11px; ">IT Development</td> </tr> <tr> <td style="font-size: 11px; ">7</td> <td style="font-size: 11px; ">User</td> <td style="font-size: 11px; ">Name</td> <td style="font-size: 11px;">Unknown</td> <td style="font-size: 11px; ">username@gmail.com</td> <td style="font-size: 11px; ">IT Development</td> </tr> <tr> <td style="font-size: 11px; ">8</td> <td style="font-size: 11px; ">User</td> <td style="font-size: 11px; ">Name</td> <td style="font-size: 11px;">Unknown</td> <td style="font-size: 11px; ">username@gmail.com</td> <td style="font-size: 11px; ">IT Development</td> </tr> <tr> <td style="font-size: 11px; ">9</td> <td style="font-size: 11px; ">User</td> <td style="font-size: 11px; ">Name</td> <td style="font-size: 11px;">Unknown</td> <td style="font-size: 11px; ">username@gmail.com</td> <td style="font-size: 11px; ">IT Development</td> </tr> </tbody> </table> </div></div></body>
</html>

HTML table with 100% width, with vertical scroll inside tbody

In order to make <tbody> element scrollable, we need to change the way it's displayed on the page i.e. using display: block; to display that as a block level element.

Since we change the display property of tbody, we should change that property for thead element as well to prevent from breaking the table layout.

So we have:

thead, tbody { display: block; }

tbody {
height: 100px; /* Just for the demo */
overflow-y: auto; /* Trigger vertical scroll */
overflow-x: hidden; /* Hide the horizontal scroll */
}

Web browsers display the thead and tbody elements as row-group (table-header-group and table-row-group) by default.

Once we change that, the inside tr elements doesn't fill the entire space of their container.

In order to fix that, we have to calculate the width of tbody columns and apply the corresponding value to the thead columns via JavaScript.

Auto Width Columns

Here is the jQuery version of above logic:

// Change the selector if needed
var $table = $('table'),
$bodyCells = $table.find('tbody tr:first').children(),
colWidth;

// Get the tbody columns width array
colWidth = $bodyCells.map(function() {
return $(this).width();
}).get();

// Set the width of thead columns
$table.find('thead tr').children().each(function(i, v) {
$(v).width(colWidth[i]);
});

And here is the output (on Windows 7 Chrome 32):

Vertical scroll inside tbody

Working demo.

Full Width Table, Relative Width Columns

As the original poster needed, we could expand the table to 100% of width of its container, and then using a relative (Percentage) width for each columns of the table.

table {
width: 100%; /* Optional */
}

tbody td, thead th {
width: 20%; /* Optional */
}

Since the table has a (sort of) fluid layout, we should adjust the width of thead columns when the container resizes.

Hence we should set the columns' widths once the window is resized:

// Adjust the width of thead cells when *window* resizes
$(window).resize(function() {
/* Same as before */
}).resize(); // Trigger the resize handler once the script runs

The output would be:

Fluid Table with vertical scroll inside tbody

Working demo.



Browser Support and Alternatives

I've tested the two above methods on Windows 7 via the new versions of major Web Browsers (including IE10+) and it worked.

However, it doesn't work properly on IE9 and below.

That's because in a table layout, all elements should follow the same structural properties.

By using display: block; for the <thead> and <tbody> elements, we've broken the table structure.

Redesign layout via JavaScript

One approach is to redesign the (entire) table layout. Using JavaScript to create a new layout on the fly and handle and/or adjust the widths/heights of the cells dynamically.

For instance, take a look at the following examples:

  • jQuery .floatThead() plugin (a floating/locked/sticky table header plugin)
  • jQuery Scrollable Table plugin. (source code on github)
  • jQuery .FixedHeaderTable() plugin (source code on github)
  • DataTables vertical scrolling example.

Nesting tables

This approach uses two nested tables with a containing div. The first table has only one cell which has a div, and the second table is placed inside that div element.

Check the Vertical scrolling tables at CSS Play.

This works on most of web browsers. We can also do the above logic dynamically via JavaScript.

Table with fixed header on scroll

Since the purpose of adding vertical scroll bar to the <tbody> is displaying the table header at the top of each row, we could position the thead element to stay fixed at the top of the screen instead.

Here is a Working Demo of this approach performed by Julien.
It has a promising web browser support.

And here a pure CSS implementation by Willem Van Bockstal.



The Pure CSS Solution

Here is the old answer. Of course I've added a new method and refined the CSS declarations.

Table with Fixed Width

In this case, the table should have a fixed width (including the sum of columns' widths and the width of vertical scroll-bar).

Each column should have a specific width and the last column of thead element needs a greater width which equals to the others' width + the width of vertical scroll-bar.

Therefore, the CSS would be:

table {
width: 716px; /* 140px * 5 column + 16px scrollbar width */
border-spacing: 0;
}

tbody, thead tr { display: block; }

tbody {
height: 100px;
overflow-y: auto;
overflow-x: hidden;
}

tbody td, thead th {
width: 140px;
}

thead th:last-child {
width: 156px; /* 140px + 16px scrollbar width */
}

Here is the output:

Table with Fixed Width

WORKING DEMO.

Table with 100% Width

In this approach, the table has a width of 100% and for each th and td, the value of width property should be less than 100% / number of cols.

Also, we need to reduce the width of thead as value of the width of vertical scroll-bar.

In order to do that, we need to use CSS3 calc() function, as follows:

table {
width: 100%;
border-spacing: 0;
}

thead, tbody, tr, th, td { display: block; }

thead tr {
/* fallback */
width: 97%;
/* minus scroll bar width */
width: -webkit-calc(100% - 16px);
width: -moz-calc(100% - 16px);
width: calc(100% - 16px);
}

tr:after { /* clearing float */
content: ' ';
display: block;
visibility: hidden;
clear: both;
}

tbody {
height: 100px;
overflow-y: auto;
overflow-x: hidden;
}

tbody td, thead th {
width: 19%; /* 19% is less than (100% / 5 cols) = 20% */
float: left;
}

Here is the Online Demo.

Note: This approach will fail if the content of each column breaks the line, i.e. the content of each cell should be short enough.


In the following, there are two simple example of pure CSS solution which I created at the time I answered this question.

Here is the jsFiddle Demo v2.

Old version: jsFiddle Demo v1

Table Width 100% with Overflow Scroll

You can't do it by changing display alone for the table, but there are a couple of ways you can achieve this.

1. Add a "scrolling" container div

You can up the standard table in a container div and give it the overflow: auto;, so it will have the scroll bar.

table          { width: 100%; }
.scrollwrapper { overflow: auto; }

This means the table will stretch to at least 100% of the width even if it is not wide enough on its own, and if the content makes it wider than 100% them the div gets a scrollbar.

Working Example:

table {
width: 100%;
border: 1px solid blue;
}

.scrollwrapper {
overflow: auto;
}

td {
border: 1px solid #aaa;
}
<h3>Scrolling Wrapper - Wide Table</h3>

<div class="scrollwrapper">
<table>
<tr>
<td>thisisoneverylongwordthatwillnotwrapinthetablecell</td>
<td>thisisoneverylongwordthatwillnotwrapinthetablecell</td>
<td>thisisoneverylongwordthatwillnotwrapinthetablecell</td>
</tr>
<tr>
<td>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent finibus nulla et lorem imperdiet, eu malesuada enim viverra.</td>
<td>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent finibus nulla et lorem imperdiet, eu malesuada enim viverra.</td>
<td>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent finibus nulla et lorem imperdiet, eu malesuada enim viverra.</td>
</tr>
</table>
</div>

<h3>Scrolling Wrapper - Narrow Table</h3>

<div class="scrollwrapper">
<table>
<tr>
<td>Column 1</td>
<td>Column 2</td>
<td>Column 3</td>
</tr>
<tr>
<td>Short text</td>
<td>Short text</td>
<td>Short text</td>
</tr>
</table>
</div>


Related Topics



Leave a reply



Submit