Setting a max height on a table - html

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?

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.

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

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

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

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;
}

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;
}

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

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

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/

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>

<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

Related

How to pad cell content to center <td>

If I have a fixed length text then I can easily center it for example
However, lets say there are data with variable length,
Centering the content of Nickname will affect readability. Is there a way to pad the content and centering it base on the longest length?
<td>
<div style="padding-left: 30%;">
...content
</div>
</td>
The value "30%" is just rough estimate for nickname.
However this 30 percent will changed if the column is expecting a longer data. What is a good way to programatically determine this value that I put as "30" ?
Update, centering text is not what I am looking for. I want to center text AND left align, centering text alone will give me
Visual representation of what I want
You need javascript to determine the width of the content and the table data width.
var td = document.querySelectorAll('td > div');
var width = 0;
var clientWidth = 0;
// determine the width
[].forEach.call(td, function(e) {
clientWidth = e.parentNode.clientWidth; // the width is the same for all td's
if (e.clientWidth > width) {
width = e.clientWidth;
}
});
// set the padding
[].forEach.call(td, function(e) {
e.style.paddingLeft = (clientWidth - width) / 2 + 'px';
e.style.paddingRight = (clientWidth - width) / 2 + 'px';
});
table {
border-collapse: collapse;
}
th {
text-align: center;
}
th, td {
border: 1px solid #000;
}
td > div {
display: inline-block; /* set this because we want to calculate the width, block element has 100% */
padding: 10px 0;
}
<table style="width: 50%">
<tr>
<th>Nickname</th>
</tr>
<tr>
<td><div>Data 1 Data 1Data 1Data 1</div></td>
</tr>
<tr>
<td><div>Data 2</div></td>
</tr>
<tr>
<td><div>Data 3</div></td>
</tr>
<tr>
<td><div>Data 4</div></td>
</tr>
<tr>
<td><div>Data 5</div></td>
</tr>
<tr>
<td><div>Data 6</div></td>
</tr>
<tr>
<td><div>Data 7</div></td>
</tr>
<tr>
<td><div>Data 8</div></td>
</tr>
</table>
Change the hardcoded table width to see the effect.
you can try by mentioning pixels size
<td>
<div style="padding-left: 30px;">
...content
</div>
</td>
Try this,
td{
padding:5px;
text-align:center;
}
so to make it responsive you should use bootstrap 3
try this you will definitely get your answer
bootstrap tables
and there classes
<tr class="something">
<td class="col-md-2">A</td>
<td class="col-md-3">B</td>
<td class="col-md-6">C</td>
<td class="col-md-1">D</td>
</tr>
Update
Technically this answer is correct but we are unable to see it visually so according to me the best way to do this is to add same left and right padding to both <th> and <td> and remove text-align:center from <th>. This is just my opinion. We will wait and see what others think about it. :)
Instead of adding padding to one side you need to add it both the sides.
table tr td{
padding:5px 15%;
}
I have created a simple example.
table{
width:200px;
}
table tr th{
background:#ccc;
text-align:left;
padding:5px 15%;
}
table tr td{
padding:5px 15%;
background:#eee;
}
<table>
<tr>
<th>Nickname</th>
</tr>
<tr>
<td>One</td>
</tr>
<tr>
<td>Big Name</td>
</tr>
<tr>
<td>A Very Big Name</td>
</tr>
<tr>
<td>This is a very big name</td>
</tr>
</table>

Odd TABLE sizing behaviour

I can't understand why the table sizing is working the way it is. Here is my example HTML:
<!DOCTYPE html>
<html>
<head>
<title>Table sizing test</title>
</head>
<body>
<style>
.tab-strip {
overflow: hidden;
white-space: nowrap;
}
.tab-strip .tab-button {
display: inline-block;
}
.tab-strip .tab-button td {
background-color: yellow;
}
.tab-strip .tab-button td:first-child {
background-color: green !important;
width: 100px;
}
</style>
<div>
<table align="center" border="1">
<tr>
<td valign="top">
<div class="tab-strip">
<table class="tab-button">
<tr>
<td></td>
<td>TEST1</td>
</tr>
</table>
<table class="tab-button">
<tr>
<td></td>
<td>TEST2</td>
</tr>
</table>
<table class="tab-button">
<tr>
<td></td>
<td>TEST3</td>
</tr>
</table>
<table class="tab-button">
<tr>
<td></td>
<td>TEST4</td>
</tr>
</table>
<table class="tab-button">
<tr>
<td></td>
<td>TEST5</td>
</tr>
</table>
<table class="tab-button">
<tr>
<td></td>
<td>TEST6</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</div>
</body>
</html>
I've put it in a jsFiddle here: http://jsfiddle.net/90674xsg/
When the window is made narrower, the table keeps shrinking (smaller than its content) until a certain point, and then stops (causing a horizontal scrollbar to appear in the result window). What determines this minimum width, though?
UPDATE:
It's been pointed out to me that the table width is determined by adding up the content-derived width of cells that actually contain content. So the "TESTx" cells' widths are counted, but the empty cell widths are ignored even though they have a fixed width of 100px. How can i make the minimum table width include their widths?
Tables are kind of weird, there's good reason that modern web development has steered away from them.
Adding the css min-width property seems to do the trick for me, but I only tested in chrome.
.tab-strip .tab-button td:first-child {
background-color: green !important;
width: 100px;
min-width: 100px;
}
See updated fiddle here. If that doesn't work, you can try forcing it to stay open with padding instead of width - or add an empty div to the td that has a width of 100px.

Maximize CSS table-cell width

On my website I have a CSS table with two table cells.
One is 400px wide, and I want the other one to take up the rest of the page.
How do I do that? I have tried applying width 100% to it, but that doesn't work on chrome, and width: auto doesn't work at all.
.wrapper{
display: table;
width: 100vw;
max-width: 100vw;
}
[...]
.sidebar{
display: table-cell;
border-right: 1px solid #707070;
width: 400px;
}
[...]
.content{
display: table-cell;
width: 100%;
}
HTML:
<div class="wrapper">
<div class="sidebar">
<!-- Stuff -->
</div>
<div class="content">
<!-- Titles and text, all that usual blog stuff. Oh, and a big, wide header. -->
</div>
</div>
Set your wrapper to be display:table and not display:table-cell because otherwise the wrapper gets an anonymous table wrapper at auto width (shrink to fit for tables).
.wrapper{
display: table;
width: 100%;
table-layout:fixed;
}
I wouldn't use vw for the width either as that includes the scrolbar and will cause a horizontal scrollbar when content is below the fold.
Apply style="width:100%" to the table element, keeping the 400px limit on the first cell. The second cell will expand to meet the table's width.
The table should automatically scale to full width (assuming it's width is 100%), even with one column fixed and the other(s) flexible. I threw up a little test/example # http://jsfiddle.net/41uc6Lsq/1/
<table width="100%">
<thead>
<tr>
<th width="20px">Col 1</th>
<th>Col 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
<table width="100%">
<tbody>
<tr>
<td width="20px">1</td>
<td>2</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
EDIT: just saw your CSS edit - could you post the HTML too please?

Fixed column width with horizontal scrolling doesn't show when the column widths larger than container

I am trying to have a table with fixed column widths and horizontal scrolling when the width of the columns is greater than the containing block.
The only time the fixed column widths work is when the sum of column widths < containing block (i.e. no scroll)
Otherwise, the fixed column widths seem to get ignored. Anyone know how to do this? here's my html and css.
<div class="scroll-content-grid21">
<div class="ExtraScrollableContainerDiv">
<table class="regular" style="width:1440px">
<tr>
<th>Item #</th>
<th>Description</th>
<th>Rate</th>
<th>Qty</th>
<th>Price</th>
<th>Amount</th>
<th>Prev Qty</th>
<th>Prev Amt</th>
etc. more columns
</tr>
<%
for (int i = 0; i < this.Model.BusinessObject.Items.Count; i++)
{
%>
<tr>
<td style="width:80px"><%: this.Model.BusinessObject.Items[i].SnapshotReferenceNumber %></td>
<td style="width:240px"><%: this.Model.BusinessObject.Items[i].SnapshotShortDescription%></td>
<td style="width:80px"><%: this.Model.BusinessObject.Items[i].SnapshotUnitRate%></td>
<td style="width:80px"><%: this.Model.BusinessObject.Items[i].SnapshotQuantity%></td>
<td style="width:80px"><%: this.Model.BusinessObject.Items[i].SnapshotUnitOfMeasureId%></td>
<td style="width:80px"><%: this.Model.BusinessObject.Items[i].SnapshotAmount%></td>
<td style="width:80px"><%: this.Model.BusinessObject.Items[i].PreviousToDateQuantity%></td>
<td style="width:80px"><%: this.Model.BusinessObject.Items[i].PreviousToDateAmount%></td>
etc. more columns
</tr>
</table>
div.scroll-content-grid21
{
overflow : auto;
width: 1072px; /* notice, smaller than the table width */
height: 500px;
}
table.regular
{
table-layout:fixed;
margin-top: 0.1em;
margin-bottom: 0.1em;
border-collapse: collapse;
text-align: left;
}
The first thing I can see is that you need to give width to your table header cells (th) as well. try this to see if it helps. Also have you given {overflow-x:auto} to td and th ?
Here's a sample for anyone else who needs it:
<html>
<head>
<style>
div.outer
{
width : 500px;
overflow : auto;
}
table
{
table-layout:fixed;
width: 100%; /* same as containing div */
}
th, td
{
border: solid 1px #ccc;
}
</style>
</head>
<body>
<div class="outer">
<div class="scrollable">
<table>
<thead>
<th style="width:50px">One</th>
<th style="width:300px">Two</th>
<th style="width:200px">Three</th>
<th style="width:200px">Four</th>
<th style="width:200px">Five</th>
</thead>
<tbody>
<tr>
<td>001</td>
<td>My really long description here</td>
<td>10.0 units</td>
<td>$100.00 dollars</td>
<td>$1000.00 total</td>
</tr>
<tr>
<td>002</td>
<td>This is number 2</td>
<td>5 units</td>
<td>$5.00 dollars</td>
<td>$25.00 total</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

Make TBODY scrollable in Webkit browsers

I'm aware of this question, but none of the answers work in Safari, Chrome, etc.
The accepted strategy (as demonstrated here) is to set the tbody height and overflow properties like so:
<table>
<thead>
<tr><th>This is the header and doesn't scroll</th></tr>
</thead>
<tbody style="height:100px; overflow:auto;">
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
</tbody>
</table>
Unfortunately, this does not work in any webkit browsers. There is a bug report about it that doesn't seem to be a high priority (reported June 05).
So my question is: are there alternate strategies that do actually work? I've tried the two-table approach, but it's impossible to guarantee that the header will line up with the content. Do I just have to wait for Webkit to fix it?
Here is a working example:
http://www.imaputz.com/cssStuff/bigFourVersion.html
You have to add the display:block to the thead > tr and tbody
Using the display:block style only works if you have 1 column. If you have multiple data columns - with multiple fields - then display:block appears to make all data columns scrollable but under the 1st column (does the same in Firefox - which is the only browser I know that does tbody scrolling nicely). Incidentally, on Firefox - you can use the overflow-x: hidden style to suppress the horizontal scroll.
I realized that the issue I mention only occurs if you are not specifying a width for the th & td elements - if you can fix the column widths then it works. Problem for me is I can't fix the column widths.
Try the first method of this page, pure CSS with a single table (2 divs around the table, and the thead is positionned absolute) : http://www.cssplay.co.uk/menu/tablescroll.html
Seems to work on FF4/IE9/IE8 in addition to IE7/FF3.6.
I had the same issue and wrote a jQuery script to do this for me... uses two table elements and formats the css accordingly. Hope this helps others who have the same issue...
http://jsfiddle.net/pe295/1/
I saw Sean Haddy's excellent solution and took the liberty of making some edits:
Use classes instead of ID, so one jQuery script could be reused for
multiple tables on one page
Added support for semantic HTML table elements like caption, thead, tfoot, and tbody
Made scrollbar optional so it won't appear for tables that are "shorter" than the scrollable height
Adjusted scrolling div's width to bring the scrollbar up to the right edge of the table
Made concept accessible by
using aria-hidden="true" on injected static table header
and leaving original thead in place, just hidden with jQuery and set aria-hidden="false"
Showed examples of multiple tables with different sizes
Sean did the heavy lifting, though. Thanks to Matt Burland, too, for pointing out need to support tfoot.
Please see for yourself at http://jsfiddle.net/jhfrench/eNP2N/
A faced the same problem long ago, and I finally set out the two tables approach. This is the result: http://jsfiddle.net/bGr4V/3/, it works for all browsers (IE6+ incl).
In this jsFiddle you can play with a clean version.
My solution was to add a fix cell <th class="fix"> </th> in thead to fill the space of the scroll bar in the tbody, then give one column a variable width (<td class="grow">), so the header fix cell wouldn't unmatch on resizing.
HTML:
<div class="fixed_table">
<div class="head">
<table>
<thead>
<tr>
<th>Column header</th>
<th class="grow">Column header</th>
<th class="fix"> </th>
</tr>
</thead>
</table>
<div class="body">
<table class="full_table">
<caption class="caption">Caption</caption>
<tbody>
<tr>
<td>Data</td>
<td class="grow">Data</td>
</tr>
<tr>
<td>...</td>
<td>...</td>
</tr>
<tr>
<td>...</td>
<td>...</td>
</tr>
</tbody>
</table>
</div>
</div>
CSS: has * and _ hack for ie6-7, and a -webkit specific for the header fix-cell matching scroll width in each case.
.fixed_table table {
table-layout: fixed;
width: auto;
border-width: 0;
padding: 0;
border-collapse: collapse;
}
.fixed_table .body {
overflow: scroll;
overflow-x: hidden;
max-height: 10.75em;
min-height: 2.5em;
padding-bottom: 0.8em;
*padding-right: 17px; /*ie7 & ie6*/
_padding-right: 0; /*ie6*/
_height: 10em ;
}
.fixed_table th, .fixed_table td {
width: 4.7em;
}
.fixed_table .grow {
width: auto;
}
.fixed_table .fix {
width: 16px;
*width: 17px; /*ie7 & ie6*/
_width: 16px; /*ie6*/
}
/* webkit specific */
#media screen and (-webkit-min-device-pixel-ratio:0) {
.fixed_table .fix{ width: 17px }
}
Thought I'd throw my solution into the mix - http://tjvantoll.com/2012/11/10/creating-cross-browser-scrollable-tbody/.
It takes the same basic route as #Michael Koper's solution but includes a workaround so the table will look correct in IE back to IE6.
I solve the width issue by giving the <table> a table-layout: fixed and explicitly assigning width to cells in each column. Not ideal but it does produce a semantic table that will align cross browser regardless of whether a scrollbar is needed.
Demo: http://codepen.io/tjvantoll/pen/JEKIu
I developed javascript solution for the above problem
which works only in Firefox 7+ as i have tested only in FF
I came to this thread and found solution pointed by Michael Koper
In this solution three important things are done
1) fix the column width
2) thead > tr display is set to block
3) tbody display is set to block
as others have mentioned there problem to fix the width , i am also in same position;
even i cant fix the width statically
so i thought i will fix the width dynamically ( after table is rendered in browser)
and this did the trick :)
following is the solution in javascript which works only in FF
( i have tested only in FF , i dont have access to other browsers )
function test1(){
var tbodys = document.getElementsByTagName("TBODY");
for(var i=0;i<tbodys.length;i++){
do_tbodyscroll(tbodys[i]);
}
}
function do_tbodyscroll(_tbody){
// get the table node
var table = _tbody.parentNode;
// first row of tbody
var _fr = _tbody.getElementsByTagName("TR")[0];
// first row cells ..
var _frcells = _fr.cells;
// Width array , width of each element is stored in this array
var widtharray = new Array(_frcells.length);
for(var i=0;i<_frcells.length;i++){
widtharray[i] = _frcells[i].scrollWidth;
}
// Apply width to first row
for(var i=0;i<_frcells.length;i++){
_frcells[i].width = widtharray[i];
}
// Get the Last row in Thead ...
// COLGROUPS USING COLSPAN NOT YET SUPPORTED
var thead = table.getElementsByTagName("THEAD")[0];
var _rows = thead.getElementsByTagName("TR");
var tableheader = _rows[_rows.length - 1];
var headercells = tableheader.cells;
// Apply width to header ..
for(var i=0;i<headercells.length;i++){
headercells[i].width = widtharray[i];
}
// ADD 16 Pixel of scroll bar to last column ..
headercells[headercells.length -1 ].width = widtharray[headercells.length -1] + 16;
tableheader.style.display = "block";
_tbody.style.display = "block";
}
This solutions finds out what is the width of column from browser
and set again the same width to columns ( header and first row of tbody )
after the width is set; thead > tr and tbody display is set to block
Hope this solution is useful for all of you ..
if you can extend it to other browsers please reply to this post
This is really quite hacky but maybe it will help someone somewhere...
http://jsfiddle.net/yUHCq/1/
It uses columns instead of rows so processing it would essentially be done backwards.
Transitional DOCTYPE added for IE compatibility.
It may be overkill for this question, but YUI still provides possibly the best free cross-browser datatable. It can be used for read-only data as well.
YUI 2 DataTable
YUI 3 DataTable
Click on the examples there to see scrollable samples. Since, I am a newbie to stackoverflow, I can only post these two links.
Add display:block; This will also remove the unnecessary horizontal scroll in FireFox as well. You are also, no doubt, aware that neither example works in MSIE 8.
<table>
<thead>
<tr><th>This is the header and doesn't scroll</th></tr>
</thead>
<tbody style="height:100px; overflow:auto;display:block;">
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
<tr><td>content that scrolls</td></tr>
</tbody>
</table>
There is an example here that works in IE5+, Firefox and Chrome. However, it uses fixed width columns.
http://www.cssplay.co.uk/menu/tablescroll.html
If anyone needs it to work in IE quirks mode, here is how I changed and simplified I.G. Pascual's code to work:
.fixed_table{
overflow: scroll;
overflow-x: hidden;
max-height: 300px;
height: 300px;
min-height: 50px;
padding-right:0;
}
#datatable td
{
padding:3px;
text-align: center;
width: 9%;
vertical-align: middle;
background-color: #343435;
color: #E0E0E3;
overflow:hidden;
}
<div class="head">
<table>
<thead>
<tr>
<th>Time (GMT)</th>
<th>Price</th>
</tr>
</thead>
</table>
</div>
<div class="fixed_table">
<table id="datatable" cellspacing="1" cellpadding="1">
<tbody></tbody>
</table>
</div>
Let the table draw as it's way and calculate each column's width and set it in to each heading. Headings are made with divisions and then we can let the table to be scrolled free.
<!DOCTYPE html>
<html>
<head>
<style>
.t_heading{
margin-top: 20px;
font-family: Verdana, Geneva, sans-serif;
background-color: #4CAF50;
}
.heading{
background-color: #4CAF50;
color: white;
float:left;
padding: 8px 0PX 8PX 0PX;
border-bottom: 1px solid #ddd;
height: 20px;
text-align: left;
}
.t_data{
overflow-y: scroll;
overflow-x: hidden;
height:0px;
width: 100%;
}
.t_content{
border-collapse: collapse;
font-family: Verdana, Geneva, sans-serif;
width: 100%;
}
.column1,.column2,.column3,.column4{
padding: 8px 0PX 8PX 0PX;
text-align: left;
border-bottom: 1px solid #ddd;
}
.t_row:hover{
background-color:#f5f5f5;
}
</style>
<script>
function setBody(){
var body = document.body,
html = document.documentElement;
var height = Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight );
height = height-300;
/*
** By changing the subtraction value, You can fit the table in to the screen correctly.
** Make sure not to come the hscroll.
** Or you can set fixed height with css for the div as your wish.
*/
document.getElementById("t_data").style.height = height+"px";
setColumnWidth("column1");
setColumnWidth("column2");
setColumnWidth("column3");
setColumnWidth("column4");
}
function setColumnWidth(o){
var object = o;
var x = document.getElementsByClassName(object);
var y = x[0].clientWidth;
document.getElementById(object).style.width = y+"px";
}
</script>
</head>
<body onload="setBody()">
<div class="t_heading">
<div class="heading" id="column1">Heading 1</div>
<div class="heading" id="column2">Heading 2</div>
<div class="heading" id="column3">Heading 3</div>
<div class="heading" id="column4">Heading 4</div>
</div>
<div class="t_data" id="t_data">
<table class="t_content">
<tr class='t_row'>
<td class='column1'>Column1 Row 0</td>
<td class='column2'>Column2 Row 0</td>
<td class='column3'>Column3 Row 0</td>
<td class='column4'>Column4 Row 0</td>
</tr><tr class='t_row'>
<td class='column1'>Column1 Row 1</td>
<td class='column2'>Column2 Row 1</td>
<td class='column3'>Column3 Row 1</td>
<td class='column4'>Column4 Row 1</td>
</tr><tr class='t_row'>
<td class='column1'>Column1 Row 2</td>
<td class='column2'>Column2 Row 2</td>
<td class='column3'>Column3 Row 2</td>
<td class='column4'>Column4 Row 2</td>
</tr><tr class='t_row'>
<td class='column1'>Column1 Row 3</td>
<td class='column2'>Column2 Row 3</td>
<td class='column3'>Column3 Row 3</td>
<td class='column4'>Column4 Row 3</td>
</tr><tr class='t_row'>
<td class='column1'>Column1 Row 4</td>
<td class='column2'>Column2 Row 4</td>
<td class='column3'>Column3 Row 4</td>
<td class='column4'>Column4 Row 4</td>
</tr><tr class='t_row'>
<td class='column1'>Column1 Row 5</td>
<td class='column2'>Column2 Row 5</td>
<td class='column3'>Column3 Row 5</td>
<td class='column4'>Column4 Row 5</td>
</tr><tr class='t_row'>
<td class='column1'>Column1 Row 6</td>
<td class='column2'>Column2 Row 6</td>
<td class='column3'>Column3 Row 6</td>
<td class='column4'>Column4 Row 6</td>
</tr><tr class='t_row'>
<td class='column1'>Column1 Row 7</td>
<td class='column2'>Column2 Row 7</td>
<td class='column3'>Column3 Row 7</td>
<td class='column4'>Column4 Row 7</td>
</tr><tr class='t_row'>
<td class='column1'>Column1 Row 8</td>
<td class='column2'>Column2 Row 8</td>
<td class='column3'>Column3 Row 8</td>
<td class='column4'>Column4 Row 8</td>
</tr><tr class='t_row'>
<td class='column1'>Column1 Row 9</td>
<td class='column2'>Column2 Row 9</td>
<td class='column3'>Column3 Row 9</td>
<td class='column4'>Column4 Row 9</td>
</tr><tr class='t_row'>
<td class='column1'>Column1 Row 10</td>
<td class='column2'>Column2 Row 10</td>
<td class='column3'>Column3 Row 10</td>
<td class='column4'>Column4 Row 10</td>
</tr>
<!--
<?php
$data = array();
for($a = 0; $a<50; $a++)
{
$data[$a] = array();
$data[$a][0] = "Column1 Row ".$a;
$data[$a][1] = "Column2 Row ".$a;
$data[$a][2] = "Column3 Row ".$a;
$data[$a][3] = "Column4 Row ".$a;
}
/*
** supose you have data in an array.. which red from database. The table will draw using array data. Or you can draw the table manualy.
** tip: If using manual table, No need of
** 'var x = document.getElementsByClassName(object); var y = x[0].clientWidth;'.
** You can just set ID of first row's cells in to some name and use it to read width.
*/
for($i=0;$i<sizeof($data);$i++){
echo "<tr class='t_row'><td class='column1'>".$data[$i][0]."</td><td class='column2'>".$data[$i][1]."</td><td class='column3'>".$data[$i][2]."</td><td class='column4'>".$data[$i][3]."</td></tr>";
}
?>
-->
</table>
</div>
</body>
</html>