table with fixed thead and scrollable tbody
This solution fulfills all 5 requirements:
table { width: 100%;}
table, td { border-collapse: collapse; border: 1px solid #000;}
thead { display: table; /* to take the same width as tr */ width: calc(100% - 17px); /* - 17px because of the scrollbar width */}
tbody { display: block; /* to enable vertical scrolling */ max-height: 200px; /* e.g. */ overflow-y: scroll; /* keeps the scrollbar even if it doesn't need it; display purpose */}
th, td { width: 33.33%; /* to enable "word-break: break-all" */ padding: 5px; word-break: break-all; /* 4. */}
tr { display: table; /* display purpose; th's border */ width: 100%; box-sizing: border-box; /* because of the border (Chrome needs this line, but not FF) */}
td { text-align: center; border-bottom: none; border-left: none;}
<table> <thead> <tr> <th>Table Header 1</th> <th>Table Header 2</th> <th>Table Header 3</th> </tr> </thead> <tbody> <tr> <td>Data1111111111111111111111111</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data2222222222222222222222222</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data3333333333333333333333333</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> </tr> </tbody></table>
Table fixed header and scrollable body
Here is the working solution:
table { width: 100%;}
thead, tbody, tr, td, th { display: block; }
tr:after { content: ' '; display: block; visibility: hidden; clear: both;}
thead th { height: 30px;
/*text-align: left;*/}
tbody { height: 120px; overflow-y: auto;}
thead { /* fallback */}
tbody td, thead th { width: 19.2%; float: left;}
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"/>
<table class="table table-striped"> <thead> <tr> <th>Make</th> <th>Model</th> <th>Color</th> <th>Year</th> </tr> </thead> <tbody> <tr> <td class="filterable-cell">Ford</td> <td class="filterable-cell">Escort</td> <td class="filterable-cell">Blue</td> <td class="filterable-cell">2000</td> </tr> <tr> <td class="filterable-cell">Ford</td> <td class="filterable-cell">Escort</td> <td class="filterable-cell">Blue</td> <td class="filterable-cell">2000</td> </tr> <tr> <td class="filterable-cell">Ford</td> <td class="filterable-cell">Escort</td> <td class="filterable-cell">Blue</td> <td class="filterable-cell">2000</td> </tr> <tr> <td class="filterable-cell">Ford</td> <td class="filterable-cell">Escort</td> <td class="filterable-cell">Blue</td> <td class="filterable-cell">2000</td> </tr> </tbody></table>
Fix thead on page scroll
You can use Lobstrosity's code with a slight modification: position: fixed
instead of absolute
.
position: fixed
is now widely adopted by all browsers including IE8 and onwards. BTW fixed renders much nicer on mobile/tablet devices than position: absolute
.
I found that on a table with dynamic widths for each column, the absolutely positioned <thead> would lose the widths of the rest of the columns, so to fix this I came up with the following code:
What this code does is as follows:
Determines the widths of each column in your table by looking up the CSS widths of the first <tbody> <tr> <td> row and storing these in an array for later. When the user scrolls the class 'fixed' is added to the <thead> (Default browser behaviour will alter the widths of the <th>'s and they won't match up with the <tbody>. So to fix this we retroactively set the widths of the <th> to the values we've read earlier.
Anyway here's the code:
CSS
table.entries {width: 100%;border-spacing: 0px;margin:0;}
table.entries thead.fixed {position:fixed;top:0;}
HTML
<table class="entries" id="entriestable">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Location</th>
<th>DOB</th>
<th>Opt in</th>
<th>Added</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name">Ricky Bobby</td>
<td>ricky.bobby@email.com</td>
<td class="addy"><i>Kent, GB</i></td>
<td class="dob">20/08/1984</td>
<td>Yes</td>
<td class="date">4 hours ago</td>
</tr>
</tbody>
</table>
JavaScript
TableThing = function(params) {
settings = {
table: $('#entriestable'),
thead: []
};
this.fixThead = function() {
// empty our array to begin with
settings.thead = [];
// loop over the first row of td's in <tbody> and get the widths of individual <td>'s
$('tbody tr:eq(1) td', settings.table).each( function(i,v){
settings.thead.push($(v).width());
});
// now loop over our array setting the widths we've got to the <th>'s
for(i=0;i<settings.thead.length;i++) {
$('thead th:eq('+i+')', settings.table).width(settings.thead[i]);
}
// here we attach to the scroll, adding the class 'fixed' to the <thead>
$(window).scroll(function() {
var windowTop = $(window).scrollTop();
if (windowTop > settings.table.offset().top) {
$("thead", settings.table).addClass("fixed");
}
else {
$("thead", settings.table).removeClass("fixed");
}
});
}
}
$(function(){
var table = new TableThing();
table.fixThead();
$(window).resize(function(){
table.fixThead();
});
});
Tailwind css table with fixed header and scrolling tbody vertically
You could add a max-height
to your table's parent div and
set position:sticky
and top:0
for your thead
<div class="table-wrp block max-h-96">
<table class="w-full">
<thead class="bg-white border-b sticky top-0">
<!-- table head content -->
</thead>
<tbody class="h-96 overflow-y-auto">
<!-- table body content -->
</tbody>
</table>
</div>
Example
<script src="https://cdn.tailwindcss.com"></script>
<div class="min-h-screen bg-gray-100">
<main>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg py-4 px-4">
<form class="mb-4" method="POST" action="https://shipping.local/login">
<div class="address">
<div class="item mb-2 md:flex md:flex-wrap md:justify-between">
<div wire:id="rbWM5jbW8w1GcT2ql3DF" class="container w-full px-4 sm:px-8">
<div class="flex flex-col">
<div class="overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="py-2 inline-block w-full sm:px-6 lg:px-8">
<div class="table-wrp block max-h-96">
<table class="w-full">
<thead class="bg-white border-b sticky top-0">
<tr>
<th scope="col" class="text-md font-medium text-gray-900 px-6 py-4 text-left">
Select
</th>
<th scope="col" class="text-md font-medium text-gray-900 px-6 py-4 text-left">
Company
</th>
<th scope="col" class="text-md font-medium text-gray-900 px-6 py-4 text-left">
Address
</th>
</tr>
</thead>
<tbody class="h-96 overflow-y-auto">
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="1">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
BATHURST </td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="2">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
BATHURST
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="3">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
MUDGEE
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="4">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
ORANGE
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="5">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
TAREN POINT
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="1">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
BATHURST </td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="2">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
BATHURST
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="3">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
MUDGEE
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="4">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
ORANGE
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="5">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
TAREN POINT
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="1">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
BATHURST </td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="2">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
BATHURST
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="3">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
MUDGEE
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="4">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
ORANGE
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
<tr class="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<input type="checkbox" name="address" value="5">
</td>
<td class="text-sm font-extrabold text-gray-900 font-light px-6 py-4 whitespace-nowrap">
TAREN POINT
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">Address Here Address Here Address Here Address Here Address Here Address Here </td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- Livewire Component wire-end:rbWM5jbW8w1GcT2ql3DF -->
</div>
</div>
</form>
</div>
</div>
</div>
</main>
</div>
How to set tbody height with overflow scroll
If you want tbody
to show a scrollbar, set its display: block;
.
Set display: table;
for the tr
so that it keeps the behavior of a table.
To evenly spread the cells, use table-layout: fixed;
.
DEMO
CSS:
table, tr td {
border: 1px solid red
}
tbody {
display: block;
height: 50px;
overflow: auto;
}
thead, tbody tr {
display: table;
width: 100%;
table-layout: fixed;/* even columns width , fix width of table too*/
}
thead {
width: calc( 100% - 1em )/* scrollbar is average 1em/16px width, remove it from thead width */
}
table {
width: 400px;
}
If tbody
doesn't show a scroll, because content is less than height
or max-height
, set the scroll any time with: overflow-y: scroll;
. DEMO 2
<editS/updateS>
2019 - 04/2021
- Important note: this approach to making a table scrollable has drawbacks in some cases. (See comments below.) some of the duplicate answers in this thread deserves the same warning by the way
WARNING: this solution disconnects the thead and tbody cell grids; which means that in most practical cases, you will not have the cell alignment you expect from tables. Notice this solution uses a hack to keep them sort-of aligned: thead { width: calc( 100% - 1em ) }
Anyhow, to set a scrollbar, a display reset is needed to get rid of the table-layout (which will never show scrollbar).
Turning the
<table>
into a grid viadisplay:grid
/contents
will also leave a gap in between header and scrollable part, to mind about. (idem if built from divs)overflow:overlay;
has not yet shown up in Firefox ( keep watching it)position:sticky
will require a parent container which can be the scrolling one. make sure yourthead
can be sticky if you have a few rows androwspan/colspan
headers in it (it does not with chrome).
So far, there is no perfect solution yet via CSS only. there is a few average ways to choose along so it fits your own table (table-layout:fixed; is .. fixing table and column's width, but javascript could probably be used to reset those values => exit pure CSS)
Related Topics
Chrome Does Not Expand Flex Parent According to Children's Content
Removing Unwanted Table Cell Borders with CSS
Inline Form Nested Within Horizontal Form in Bootstrap 3
Hiding The Toolbars Surrounding an Embedded Pdf
Why Would The Height Increase with a Smaller Font Size
How to Make Image Caption Width to Match Image Width
How to Align Text Directly Beneath an Image
Combining Two or More Canvas Elements with Some Sort of Blending
How to Show HTML or Markdown in a Swiftui Text
How to Include Special Characters in Query Strings
Hide Text, But Have It Show Up If Copied and Pasted Without JavaScript
CSS Vertical Align Does Not Work with Float
How to Center Content in a Bootstrap Column
Center a Div Horizontally and Vertically and Keep Centered When Resizing The Parent
How to Show an Animation That Is Hidden Behind a Colored Div Using a "Reveal" Div on The Surface