This must be a stupid question, but I am not able to figure anything to do about it.
I have a simple HTML table with every element having a property 'data-value'. I need to do some operations based on that, but one column at a time. Hence, I wrote a function which only runs on the first td element of each row. I am getting the rows by running another for each function.
When I use console.log($(this)), I am getting the expected td element from the all the first columns. Now, I want to store the 'data-value' property in another variable and do stuff on it.
$(this).find('td:first-of-type').each(function() {
console.log($(this));
//returns td object
})
});
As seen here, all the td elements are correctly being logged on console.
But when I use jquery to get the property 'data-value' from it, I get undefined.
What could be the error ? Is this the best way to iterate every column's tds property ?
$('#table_canvas tbody tr').each(function() {
$(this).find('td:first-of-type').each(function() {
console.log($(this));
//returns td object
})
});
$('#table_canvas tbody tr').each(function() {
$(this).find('td:first-of-type').each(function() {
console.log($(this).attr('data-value'));
//returns tr object which does not have the 'data-value'property
})
});
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<h2>HTML Table</h2>
<table id="table_canvas" class="table table--bordered" style="width: 100%; height: 100%;">
<thead>
<tr style="text-align: right;">
<th></th>
<th>first_name</th>
<th>is_staff</th>
<th>last_name</th>
</tr>
<tr>
<th>id</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<th hello="hi">1</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
<tr>
<th>3</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
<tr>
<th>4</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
<tr>
<th>5</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
<tr>
<th>6</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
<tr>
<th>7</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
</tbody>
</table>
its been awhile i dont use javascript but i think this is work for you vanilla js
just select every second child of every tr tag
document.querySelectorAll('#table_canvas tr td:nth-child(2)').forEach( x => {
console.log(x.dataset.property);
})
Here's a simple way to obtain the data, using vanilla JavaScript:
form array of <tr> elements
map tr array to array of td data-property values
// array of <tr> elements
let trs = Array.from(document.querySelectorAll('#table_canvas tbody tr'));
// array of 'data-property' values
let props = trs.map(tr =>
tr.querySelector('td').dataset.property);
console.log('props:', JSON.stringify(props));
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
<table id="table_canvas" class="table table--bordered" style="width: 100%; height: 100%;">
<thead>
<tr style="text-align: right;">
<th></th>
<th>first_name</th>
<th>is_staff</th>
<th>last_name</th>
</tr>
<tr>
<th>id</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<th hello="hi">1</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
<tr>
<th>3</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
<tr>
<th>4</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
<tr>
<th>5</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
<tr>
<th>6</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
<tr>
<th>7</th>
<td data-property="1">1</td>
<td data-property="True">True</td>
<td data-property="1">1</td>
</tr>
</tbody>
</table>
I'm stuck with a challenge to change the background color of td elements based on the th class. Below is the html code, which has th class called bots, I've to change the background color of all the td elements below the bots class.
<table border="1" class="CSSTableGenerator" id="myTable">
<tr>
<th>Component</th>
<th>Properties</th>
<th class="bots">J10</th>
<th>J11</th>
<th>J12</th>
<th>J13</th>
</tr>
<tr>
<td>GenerateAlternateTagUrlDroplet</td>
<td>alternateTagConfiguration</td>
<td class="trueValue">/com//jec/website/seo/</td>
<td class="trueValue">/com//jec/website/seo/</td>
<td class="trueValue">/com//jec/website/seo/</td>
<td class="trueValue">/com//jec/website/seo/</td>
</tr>
<tr>
<td>AlternateTagUrlDroplet</td>
<td>tagConfiguration</td>
<td class="trueValue">/jec/website/seo/</td>
<td class="trueValue">/jec/website/seo/</td>
<td class="trueValue">/jec/website/seo/</td>
<td class="trueValue">/jec/website/seo/</td>
</tr>
</table>
Can someone please help me with jquery code to achieve this?
Many Thanks in advance.
You can use map() to return array of indexes with .bots class and then change css of td with same index.
var bots = $('tr th.bots').map(function() {
return $(this).index();
}).get()
$('tr:not(:first) td').each(function() {
if (bots.indexOf($(this).index()) != -1) $(this).css('background', 'blue')
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1" class="CSSTableGenerator" id="myTable">
<tr>
<th>Component</th>
<th>Properties</th>
<th class="bots">J10</th>
<th>J11</th>
<th class="bots">J12</th>
<th>J13</th>
</tr>
<tr>
<td>GenerateAlternateTagUrlDroplet</td>
<td>alternateTagConfiguration</td>
<td class="trueValue">/com//jec/website/seo/</td>
<td class="trueValue">/com//jec/website/seo/</td>
<td class="trueValue">/com//jec/website/seo/</td>
<td class="trueValue">/com//jec/website/seo/</td>
</tr>
<tr>
<td>AlternateTagUrlDroplet</td>
<td>tagConfiguration</td>
<td class="trueValue">/jec/website/seo/</td>
<td class="trueValue">/jec/website/seo/</td>
<td class="trueValue">/jec/website/seo/</td>
<td class="trueValue">/jec/website/seo/</td>
</tr>
</table>
One option would be to do something along the lines of:
Codepen
var nthChild = $('.bots').index() + 1; // Add 1 since index starts at 0
$("td:nth-child(" + nthChild + ")").css("background", 'yellow');
Maybe get all th.bots index and use that to color the tds.
Assuming you have jQuery:
$('th.bots').each(function(){
$('td:nth-child('+($(this).index() + 1)+')').css('background-color', 'blue');
});
Edit: Excluding other tables on same page
http://codepen.io/anon/pen/PzNZrE
$('th.bots').each(function(){
$(this).parents('table').children().find('td:nth-child('+($(this).index() + 1)+')').css('background-color', 'blue');
});
I'm trying to a add a class to every element that contains an <a> with a text so I could hide the <tr>'s that has no text! here is my HTML code and JavaScript:
$("tr a").each(function () {
var a= $(e);
if ($e.text().length > 0) {
tr.addClass("buttoneffect");
}
});
table tr {
height: 36px;
}
table tr:hover {
background-color: #BEDB7F;
}
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td>Test 1</td>
</tr>
<tr>
<td>Test 2</td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td>Test 4</td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td>Test 6</td>
</tr>
</tbody>
</table>
see this fiddle
first you are referencing e , which you didn't pass inside the event callback, and there is no tr directly accessible you have to find out the closest tr to that of a
$("tr a").each(function () {
var a= $(this);
if (a.text().length > 0) {
a.closest('tr').addClass("buttoneffect");
}
});
Also if you want the trs to be hidden, you can add css for that: fiddle
tr:not(.buttoneffect)
{
display:none;
}
$("tr a").each(function() {
var a = $(this);
if (a.text().length > 0) {
a.closest('tr').addClass("buttoneffect");
}
});
table tr {
height: 36px;
}
table tr:hover {
background-color: #BEDB7F;
}
.buttoneffect {
background: red;
}
tr:not(.buttoneffect) {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td>Test 1
</td>
</tr>
<tr>
<td>Test 2
</td>
</tr>
<tr>
<td>
</td>
</tr>
<tr>
<td>Test 4
</td>
</tr>
<tr>
<td>
</td>
</tr>
<tr>
<td>Test 6
</td>
</tr>
</tbody>
</table>
You can use .filter() find filter those elements and then call .addClass() on the filtered set to add the class
$("tr").filter(function () {
return $(this).find('a').text().trim().length > 0
}).addClass("buttoneffect");
Demo: Fiddle
use jquery parent().
$("tr a").each(function () {
var a= $(this);
if (a.text().length > 0) {
a.parnt('tr').addClass("buttoneffect");
}
});
Try this Demo Here
$("tr a").each(function () {
var a= $(this);
if (a.text().length > 0) {
a.closest('tr').addClass("buttoneffect");
}
});
I have a 2 columns TABLE with first TD containing another TABLE with 3 rows of contents and second TD with an image as below:-
<table id="myTable" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-top: 10px;">
<table>
<tbody>
<tr>
<td align="left">
Wellness and Care
</td>
</tr>
<tr>
<td align="left">
630 Woodbury Drive
</td>
</tr>
<tr>
<td align="left">
641.613.1450
</td>
</tr>
<tr>
<td align="left">
No Webaddress
</td>
</tr>
</tbody>
</table>
</td>
<td align="right">
<img src="images/phone.png" class="imgHeader" id="imgPhone">
</td>
</tr>
<tr>
<td style="padding-top: 10px;">
<table>
<tbody>
<tr>
<td align="left">
Hospital
</td>
</tr>
<tr>
<td align="left">
N/A
</td>
</tr>
<tr>
<td align="left">
641.613.1451
</td>
</tr>
<tr>
<td align="left">
No Webaddress
</td>
</tr>
</tbody>
</table>
</td>
<td align="right">
<img src="images/phone.png" class="imgHeader" id="imgPhone">
</td>
</tr>
</tbody>
</table>
I am trying to disable the image on the second column of the row, if the Value of one of the TD is "N/A". I am stuck at getting the parent TR and going to second TD to do something.
My try is as follows:
$('#myTable tr').each(function () {
if ($(this).find("td").text().trim() == "N/A") {
var cellIndex = $(this).index();
var nextTD = $(this).children('td').eq(1).index();
// I am basically stuck here in getting next TD
}
});
Any help is appreciated!!
DEMO
$('#myTable td:first-child td:contains("N/A")').parents('td').next().find('img').hide();
Try
$( '#myTable td:first-child td:contains("N/A")' ).closest('tr').closest('td').next().find('img').hide()
Demo: Fiddle
What I would do in your case is add a class for your 4 tr tags with text. Then you can just parse through each of those 4 by their class and if one of them is equal to 'N/A' you can grab the image by its ID and hide it.
HTML:
<td class="test" align="left">
Wellness and Care
</td>
JQuery:
$('.test').each(function () {
if($(this).text().trim() == 'N/A') {
$("#imgPhone").toggle();
}
});
JSFiddle: http://jsfiddle.net/ax6Mv/
This should be enough to get you started:
$( '#myTable td:first td' ).each(
function() {
if ( $( this ).text().trim() == 'N/A' ) {
$( '#myTable td' ).eq( 1 ).hide();
}
}
);
I have a large dynamic table created from database data. I need the column heading rows to remain fixed and scroll the rows an necessary.
I have tried numerous scripts all over the web trying to get this to work properly. I'd like to keep this simple and easy on browser, since some target computers are rather lame.
Here is what I'm working with:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Sample</title>
</head>
<body>
<br><br><br><br>
<table id="A" border="0" width="95%" cellspacing="0" cellpadding="0" align="center" class="base">
<tr bgcolor='gray'>
<td>
<br><br><br>
need the blue column heading rows to remain fixed, and scroll the green rows:<br>
<table id="XYZ" border="1" width="625" cellspacing="0" cellpadding="0" align="center" class="base">
<thead>
<tr>
<th width="50px" bgcolor="DeepSkyBlue" align="center" valign="middle">Col 1a</th>
<th width="50px" bgcolor="DeepSkyBlue" align="center" valign="middle">Col 1b</th>
<th width="75px" bgcolor="DeepSkyBlue" align="center" valign="middle">Col 1c</th>
<th width="100px" style="border-left:medium solid black;" colspan="3" bgcolor="DeepSkyBlue" align="center" valign="middle"><b>Col 2</th>
<th width="100px" style="border-left:medium solid black;" colspan="1" bgcolor="DeepSkyBlue" align="center" valign="middle"><b>Col 3</th>
<th width="150px" style="border-left:medium solid black;" colspan="5" bgcolor="DeepSkyBlue" align="center" valign="middle"><b>Col 4<br>more<br>more</th>
<th width="100px" style="border-left:medium solid black;" colspan="1" bgcolor="DeepSkyBlue" align="center" valign="middle"><b>Col 5</th>
</tr>
<tr>
<th bgcolor="DeepSkyBlue" colspan="3" align="center" valign="middle">Col 1</th>
<th bgcolor="DeepSkyBlue" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<th bgcolor="DeepSkyBlue" align="center" valign="middle">B</th>
<th bgcolor="DeepSkyBlue" align="center" valign="middle">C</th>
<th bgcolor="DeepSkyBlue" style="border-left:medium solid black;" align="center">1</th>
<th bgcolor="DeepSkyBlue" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<th bgcolor="DeepSkyBlue" align="center" valign="middle">4-b</th>
<th bgcolor="DeepSkyBlue" align="center" valign="middle">4-c</th>
<th bgcolor="DeepSkyBlue" align="center" valign="middle">4-d</th>
<th bgcolor="DeepSkyBlue" align="center" valign="middle">4-e</th>
<th bgcolor="DeepSkyBlue" style="border-left:medium solid black;" align="center">Z</th>
</tr>
</thead>
<tbody>
<tr>
<td bgcolor="PaleGreen" colspan="3" align="center" valign="middle">Col 1<br>more</td>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="PaleGreen" align="center" valign="middle">B</th>
<td bgcolor="PaleGreen" align="center" valign="middle">C</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-b</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-c</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-d</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-e</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[1]" size="3"></th>
</tr>
<tr>
<td bgcolor="LimeGreen" align="center" valign="middle">Col 1a</td>
<td bgcolor="LimeGreen" colspan="2" align="center" valign="middle">Col 1b+c</td>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="LimeGreen" align="center" valign="middle">B</th>
<td bgcolor="LimeGreen" align="center" valign="middle">C</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-b</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-c</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-d</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-e</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[2]" size="3"></th>
</tr>
<tr>
<td bgcolor="PaleGreen" colspan="2" align="center" valign="middle">Col 1a+b</td>
<td bgcolor="PaleGreen" align="center" valign="middle">Col 1c</td>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="PaleGreen" align="center" valign="middle">B</th>
<td bgcolor="PaleGreen" align="center" valign="middle">C</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-b</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-c</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-d</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-e</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[3]" size="3"></th>
</tr>
<tr>
<td bgcolor="LimeGreen" align="center" valign="middle">Col 1a</td>
<td bgcolor="LimeGreen" colspan="2" align="center" valign="middle">Col 1b+c<br>more</td>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="LimeGreen" align="center" valign="middle">B</th>
<td bgcolor="LimeGreen" align="center" valign="middle">C</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-b</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-c</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-d</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-e</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[4]" size="3"></th>
</tr>
<tr>
<td bgcolor="PaleGreen" colspan="2" align="center" valign="middle">Col 1a+b</td>
<td bgcolor="PaleGreen" align="center" valign="middle">Col 1c</td>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="PaleGreen" align="center" valign="middle">B</th>
<td bgcolor="PaleGreen" align="center" valign="middle">C</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-b</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-c</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-d</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-e</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[5]" size="3"></th>
</tr>
<tr>
<td bgcolor="LimeGreen" align="center" valign="middle">Col 1a</td>
<td bgcolor="LimeGreen" colspan="2" align="center" valign="middle">Col 1b+c</td>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="LimeGreen" align="center" valign="middle">B</th>
<td bgcolor="LimeGreen" align="center" valign="middle">C</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-b</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-c</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-d</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-e</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[6]" size="3"></th>
</tr>
<tr>
<td bgcolor="PaleGreen" colspan="2" align="center" valign="middle">Col 1a+b</td>
<td bgcolor="PaleGreen" align="center" valign="middle">Col 1c</td>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="PaleGreen" align="center" valign="middle">B</th>
<td bgcolor="PaleGreen" align="center" valign="middle">C</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-b</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-c</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-d</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-e</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[7]" size="3"></th>
</tr>
<tr>
<td bgcolor="LimeGreen" align="center" valign="middle">Col 1a</td>
<td bgcolor="LimeGreen" colspan="2" align="center" valign="middle">Col 1b+c<br>more<br>more</td>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="LimeGreen" align="center" valign="middle">B</th>
<td bgcolor="LimeGreen" align="center" valign="middle">C</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-b</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-c</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-d</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-e</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[8]" size="3"></th>
</tr>
<tr>
<td bgcolor="PaleGreen" colspan="2" align="center" valign="middle">Col 1a+b</td>
<td bgcolor="PaleGreen" align="center" valign="middle">Col 1c</td>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="PaleGreen" align="center" valign="middle">B</th>
<td bgcolor="PaleGreen" align="center" valign="middle">C</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-b</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-c</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-d</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-e</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[9]" size="3"></th>
</tr>
<tr>
<td bgcolor="LimeGreen" align="center" valign="middle">Col 1a</td>
<td bgcolor="LimeGreen" colspan="2" align="center" valign="middle">Col 1b+c<br>more<br>more</td>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="LimeGreen" align="center" valign="middle">B</th>
<td bgcolor="LimeGreen" align="center" valign="middle">C</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-b</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-c</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-d</th>
<td bgcolor="LimeGreen" align="center" valign="middle">4-e</th>
<td bgcolor="LimeGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[8]" size="3"></th>
</tr>
<tr>
<td bgcolor="PaleGreen" colspan="2" align="center" valign="middle">Col 1a+b</td>
<td bgcolor="PaleGreen" align="center" valign="middle">Col 1c<br>more<br>more<br>more<br>more<br>more<br>more<br>more<br>more<br>more<br>more</td>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">A</th>
<td bgcolor="PaleGreen" align="center" valign="middle">B</th>
<td bgcolor="PaleGreen" align="center" valign="middle">C</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center">1</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center" valign="middle">4-a</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-b</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-c</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-d</th>
<td bgcolor="PaleGreen" align="center" valign="middle">4-e</th>
<td bgcolor="PaleGreen" style="border-left:medium solid black;" align="center"><input type="text" NAME="b[9]" size="3"></th>
</tr>
</tbody>
</table>
<br><br><br><br>
</td>
</tr>
</table>
<br><br><br><br><br><br>
</body>
</html>
You can have the header row(s) in a separate table to the data rows using the same colgroup settings in both.
The below works fine in IE9, FF14.01 and Chrome 20.0.1132.57.
<table border="1">
<colgroup>
<td width="100px">Column 1</td>
<td width="100px">Column 2</td>
<td width="100px">Column 3</td>
<td width="16px" style="background-color: gray;"><td>
</colgroup>
</table>
<div style="position: absolute; height:75px; overflow-y:scroll; overflow-x:auto">
<table border="1">
<colgroup>
<td width="100px"></td>
<td width="100px"></td>
<td width="100px"></td>
</colgroup>
<tbody>
<tr>
<td>Row 1 - Cell 1</td>
<td>Row 1 - Cell 2</td>
<td>Row 1 - Cell 3</td>
</tr>
<tr>
// rest omitted, see DEMO for full table
</tr>
</tbody>
</table>
</div>
See DEMO
Edit -- August 3rd 2012
The only way I was able to get it to work was with a bit of trickery alright.
I separated the header as in the first example. But due to the extremly custom multiple different widths in the header, the most reliable way, keeping everything aligned, was to copy the th rows also into the second table but without text inside. That made them "invisible" but forced the columns in the second table to align as expected.
See DEMO
It feels a bit hackish and I'm sure there is a proper solution but it seems to work well in the meantime.
Edit -- August 7th 2012
Is there any way to "box" this entire table construct up in up 100% of
the screen width and change the height for height:150px; to something
more dynamic, like $(window).height()-200
There surely is a more elegant way of doing it but I was able to make the table more dynamic.
The width was less of an issue as I capped the toal width at about 95% and hard-capped the table(s) at a min-width: 600px; for the header and a min-width: 584px for the body, thus ensuring the table stays aligned at all times.
For the dynamic height I used jQuery, binding a resize function to the windows resize event:
$(document).ready(function() {
resizeTableHeight();
$(window).on("resize.resizeTableHeight", function() {
resizeTableHeight();
});
});
function resizeTableHeight() {
var headerHeight = $("#tableHeaderContainer").height();
var documentHeight = $(document).height();
var spacingHeight = 50;
$("#tableBodyContainer").height(documentHeight - headerHeight - spacingHeight);
}
When you open the fiddle the original height of the fiddle window will most likely be to high to see the dynamics. Just move the divider and shrink the view to see the re-sizing at work.
Do not forget to unbind that event when you are not showing the grid as it still will execute on resize every time.
See dynamic-grid DEMO
You will notice some styles are in the css (top-right) in the fiddle while others are not. My CSS is not very strong and some styles when I moved them from the elements into the CSS area started to be irgnored. I moved into CSS what I could and left the rest hard-coded not to break it. I'm sure someone working with CSS everyday will be able to sort that out for you.
I also added some ids to some elements for CSS and for the jQuery as required.
I suppose for the CSS it can use classes instead. I leave that to you.
Summary
I'm sure there is a way more elegant way to achieve what you want and probably some script-wiz got a plugin for it. Until then this seems to work. What could also happen is that the columns start miss-aligning close to 600 pixels again if a lot of long data is entered into the columns but as stated, this is a very personalised solution and you may need to add some dynamic calculations for some widths with jQuery over time.
Edit -- August 9th 2012
Regarding setting the width of a td I mentioned in the comments. I fixed the issue with the long text in the first column using the classes I mentioned. Works in IE, FF and Chrome.
See DEMO
I used the logic mentioned in the comments. You might find a much better naming convention. I simply used the main-column+ a on/off switch per sub-column. this works out as follows for column 1 styles:
.col01-000{
width: 0px;
}
.col01-001{
width: 75px;
}
.col01-010, .col01-100{
width: 50px;
}
.col01-011, .col01-101{
width: 125px;
}
.col01-110{
width: 100px;
}
I have assigned the first td a class of col01-100 which means 50px.
The second td has now a class of col01-011, indicating this td still belongs into the first main column but has a width of sub-column 2 (50px) and 3(75px). This adds up to 125px.
I hope this makes sense but if not I gladly continue the discussion in a chat and work the measurements out with you if that is something you want to apply.
So far I can see the measurements to be:
Col01
Col1 = colspan 3 over 175px
3 Sub-columns breaking 175px down as follows: 50px-50px-75px
Col02
Col2 = colspan 3 over 100px
3 Sub-columns breaking 100px down as follows: 40px-30px-30px
Col03
Col3 = colspan 1 over 100px
No sub-columns
Col04
Col4 = colspan 5 over 150px
5 sub-columns breaking 150px down as follows: 30px-30px-30px-30px-30px
Col05
Col5 = colspan 1 over 100px
No sub-columns
Edit: Fix for fixed position on window resize:
http://jsfiddle.net/eReBn/13/
Complete Code:
$(function() {
(function($) {
$.fn.fTable = function(o) {
var tableTmpl = '<table id="XYZ_fixed" border="1" width="625" cellspacing="0" cellpadding="0" align="center" class="base"></table>';
this.wrap('<div class="fTable_container" />');
var fc = this.parent();
fc.css('width', this.width() + 18);
this.wrap('<div class="fTable_rContainer" />');
var rc = this.parent();
rc.css('height', o.height);
var fTable = $(tableTmpl);
fTable
.addClass('fTable_fixedHead')
.html(this.find('thead').clone())
.prependTo(rc);
$(window).on('scroll resize', function () {
console.log(isScroll());
if (isScroll()) {
fTable.css('left', $(this).scrollLeft() * -1);
} else {
fTable.css('left', '');
}
});
};
function isScroll() {
var root= document.compatMode=='BackCompat'?
document.body : document.documentElement;
return root.scrollWidth>root.clientWidth;
}
})(jQuery);
$('#XYZ').fTable({
height: 300
});
});
Edit: Try below solution.. since you were ok to manually add styles and adjust table.
DEMO: http://jsfiddle.net/eReBn/12/embedded/result/
Manual:
a. Copy below CSS to your style sheet
.fTable_rContainer {
position: relative;
overflow: auto;
height: 300px; /* Height of the table */
}
.fTable_container {
width: 643px; /* Total width of the table you set + 18px (scroll size) */
}
.fTable_fixedHead {
position: fixed;
}
b. Wrap the Table with div class="fTable_container"
c. Copy the thead part of the original table and move to a new table as in DEMO.
d. Add class fTable_fixedHead to the new table
Automated with some scripts:
DEMO: http://jsfiddle.net/eReBn/11/embedded/result/
I tried to solve it using 2 tables,
Original table (untouched)
Fixed Header table(absolute positioned) over the original table
Check it out and let me know if you like it.
DEMO
Tested in Firefox & Chrome. [Will test on other browsers later today]
Full code # http://jsfiddle.net/eReBn/7/
JS:
$(function() {
(function($) {
$.fn.fTable = function(o) {
/* Preserve the attr list from original table */
var el = this[0], arr = [], it;
for (var i = 0, attrs = el.attributes, l = attrs.length; i < l; i++) {
it = attrs.item(i);
if (it.nodeName == 'id') {
arr.push(it.nodeName + '="' + it.nodeValue + '_fixed"');
} else {
arr.push(it.nodeName + '="' + it.nodeValue + '"');
}
}
var tableTmpl = '<table ' + arr.join(' ') + '></table>';
/* Wrap it inside div's */
this.wrap('<div class="fTable_container" />');
this.wrap('<div class="fTable_rContainer" />');
var rc = this.parent();
/* Clone the thead and add it to the fixed table head */
$(tableTmpl)
.addClass('fTable_fixedHead')
.html(this.find('thead').clone())
.prependTo(rc);
/* Position the fixed head table on scroll */
rc.scroll(function() {
rc.find('.fTable_fixedHead').css('top', $(this).scrollTop());
});
var _that = this;
rc.find('.fTable_fixedHead').css('left', _that.aPosition().left);
/* Position the left on resize*/
$(window).resize(function() {
rc.find('.fTable_fixedHead').css('left', _that.aPosition().left);
});
};
/* Position fix for webkit browsers */
jQuery.fn.aPosition = function() {
thisLeft = this.offset().left;
thisTop = this.offset().top;
thisParent = this.parent();
parentLeft = thisParent.offset().left;
parentTop = thisParent.offset().top;
return {
left: thisLeft - parentLeft,
top: thisTop - parentTop
}
}
})(jQuery);
});
Usage:
$('#XYZ').fTable({
height: 300
});
We used DataTables.net and solved a very similar problem quite nicely. Here is an example from their website with an advanced multi-row header. You can also sort within your sub-column categories.
I may as well provide an option for you. This assumes the browser window is being scrolled.
The idea here is that a clone of your table is made and everything but the thead is stripped out of it. It is fixed to the top of the viewport and hidden.
When the user scrolls past the top of the table, the cloned table is displayed. I have also included a resize event to handle changes to the viewport's width. There are some minor hiccups with keeping the fixed header and the table aligned horizontally, but it's not a big issue.
Here is a demo using your table as source (I moved a lot of the inline styles to CSS just to make things easier to read):
jsFiddle DEMO
$(function(){
var $window = $(window),
stickyTable = $('#XYZ'),
stickyHeader = stickyTable.clone(true),
tableTop = stickyTable.offset().top,
isSticky = false;
handleScroll();
$window.on({
scroll: handleScroll,
resize: handleResize
});
stickyHeader.find('tbody').remove();
stickyHeader.find('tfoot').remove();
stickyHeader.addClass('sticky-header').appendTo('body');
function handleScroll() {
var scrollTop = $window.scrollTop();
if(scrollTop > tableTop && !isSticky) {
stickyHeader.css('left',stickyTable.offset().left+'px').show();
isSticky = true;
} else if(scrollTop <= tableTop && isSticky) {
stickyHeader.hide();
isSticky = false;
}
}
function handleResize() {
if(isSticky) {
stickyHeader.css('left',stickyTable.offset().left+'px');
}
}
});
Some of the previously written answers were brilliant!!
I tested this in Google Chrome most of the time, due to the brilliant Chrome Developer tools for debugging Javascript on the fly, and tweaking css in realtime.
If you added jQuery with a clone function in it, you could achieve a scrollable table without squashing it into a page height, and have a floating Table header wherever you want it
The following code will clone the table header:
jQuery(document).ready(function () {
jQuery("body").append("<table class='tableheader' align='center' border='1' width='625' cellspacing='0' cellpadding='0'></table>");
jQuery(".tableheader").append(jQuery(".base2 thead").clone());
Then you need to set some static variable, and catch the scrolling event:
var headerToMove = jQuery(".tableheader");
var headerOffsetTop = headerToMove.offset().top;
var headerPosition = headerToMove.position();
jQuery(window).scroll(function () { scroll_post_header(); });
Then move the header up and down over the current header, but keep it on top of the page, if the current header scrolls out of the way.
function scroll_post_header() {
var new_position = headerOffsetTop - jQuery(window).scrollTop();
if (new_position < 0) { new_position = 0;}
if (headerPosition.top != new_position) {
headerToMove.css("top",new_position);
//headerToMove.stop().animate({ 'top': new_position }, 300);
}
if (jQuery(window).scrollTop() < 15) { headerToMove.css("top",headerOffsetTop);}
}
});
Now ad some initial CSS to the header that will be cloned. You will need to find that sweet spot where your current header is from the top, but even this can be achieved via jQuery interrogation.
.tableheader {
position: fixed;
height: 80px;
top: 160px;
left: 2.5%;
z-index: 1000;
}
The full working example can be found at: http://jsfiddle.net/webwarrior/YZ8cJ/142/
Hope this helps somewhat without changing any html.
If you .clone() the thead and put it in the table all of the columns retain their original width.
Update: I realized that IE 6 and 7 were having problems and I fixed them. The issue was that those versions of IE don't allow you to position the thead directly. As a result, I changed it so that it moves the thead tr instead, but only if the browser is IE < 8.
Another bug was that IE < 9 had problems with .prependTo(). I'm not sure if it is just IE Tester or not, but I resolved the issue by using .after().
Updated Demo
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
// http://obvcode.blogspot.com/2007/11/easiest-way-to-check-ie-version-with.html
var Browser = {
version: function() {
var version = 999; // we assume a sane browser
if (navigator.appVersion.indexOf("MSIE") != -1) {
// bah, IE again, lets downgrade version number
version = parseFloat(navigator.appVersion.split("MSIE")[1]);
}
return version;
}
}
var $thead = $('#XYZ thead'),
$new_thead = $thead.clone().hide(),
$window = $(window),
distance_from_top = $thead.offset().top,
did_scroll = false; // http://ejohn.org/blog/learning-from-twitter/
// for IE <= 7
var $tr_1, $tr_2;
// add the cloned thead
$thead.after($new_thead);
if( Browser.version() < 8 ) {
$new_thead.find('tr').css({
'position': 'absolute',
'top': 0,
'margin-left': -1
});
$tr_1 = $new_thead.find('tr:first');
$tr_2 = $new_thead.find('tr:last').css('top', $tr_1.height());
}else {
$new_thead.css({
'position': 'fixed',
'width': $thead.width(),
'top': 0
});
}
$window.scroll(function() {
if( Browser.version() < 8 ) {
did_scroll = true;
}
if( $window.scrollTop() >= distance_from_top ) {
$new_thead.show();
}else {
$new_thead.hide();
}
});
setInterval(function() {
if( did_scroll ) {
did_scroll = false;
$tr_1.css('top', $window.scrollTop());
$tr_2.css('top', $tr_1.height() + $window.scrollTop());
}
}, 250);
</script>
Edit
I didn't realize that K.M. wanted a fixed height table. If you look at my example above you'll see that the table header is fixed if the browser scrolls past the top of the table. However, from my understanding this is not what he/she wanted.
I have tested this in the following browsers on my Mac.
Safari (5.1.7)
Firefox (11.0)
Chrome (21.0.1180.75)
And I have tested this in Windows 7 with:
IE 8 and 9 using IE Tester
Firefox (5.0.1, 6.0.2, 7.0.1, 8.0.1, 10.0.2)
Chrome (12.0.742.91)
Safari (5.1.5)
It is broken in IE 6 and 7, but I didn't look into seeing if there was a fix.
Demo
var table = $('#XYZ'),
thead = table.find('thead'),
fixed_thead = thead.clone(),
// create a copy of the original table
fixed_thead_wrapper = $('<table />', {
'id': 'fixed_thead_wrapper',
'align': 'center',
'width': table.outerWidth(),
'border': '1',
'cellspacing': 0,
'cellpadding': 0
}).insertBefore(table),
// this forces the table to be in a scrollable area
table_wrapper = $('<div />', {
'id': 'fixed_table_wrapper',
'height': 300,
css: {
'overflow': 'auto'
}
});
// add the cloned thead to the new table
fixed_thead_wrapper.append(fixed_thead);
// hide the original thead.
// this is a very hackish way of doing this, but I'm not sure of a better way as of right now
table.css({
'position': 'relative',
'top': fixed_thead_wrapper.height() * -1
});
// wrap the original table
table.wrap(table_wrapper);
// line the tables up now that the scrollbar is present
fixed_thead_wrapper.css({
'position': 'relative',
'left': table.offset().left - fixed_thead_wrapper.offset().left
});
I've always used this super easy to use Plugin that handles it as easily as $('#tableID').fixedtableheader();
Works amazingly, very lightweight and flexible.
http://fixedheadertable.com/
Check out HTML table with fixed headers?. It is the best answer to the general question "how can I freeze a table header?"
Check this Fiddle
Here is the Code. Working fine in all browsers...!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Scrollable Table with Fixed Header</title>
<meta http-equiv="language" content="en-us">
<script type="text/javascript">
function removeClassName (elem, className) {
elem.className = elem.className.replace(className, "").trim();
}
function addCSSClass (elem, className) {
removeClassName (elem, className);
elem.className = (elem.className + " " + className).trim();
}
String.prototype.trim = function() {
return this.replace( /^\s+|\s+$/, "" );
}
function stripedTable() {
if (document.getElementById && document.getElementsByTagName) {
var allTables = document.getElementsByTagName('table');
if (!allTables) { return; }
for (var i = 0; i < allTables.length; i++) {
if (allTables[i].className.match(/[\w\s ]*scrollTable[\w\s ]*/)) {
var trs = allTables[i].getElementsByTagName("tr");
for (var j = 0; j < trs.length; j++) {
removeClassName(trs[j], 'alternateRow');
addCSSClass(trs[j], 'normalRow');
}
for (var k = 0; k < trs.length; k += 2) {
removeClassName(trs[k], 'normalRow');
addCSSClass(trs[k], 'alternateRow');
}
}
}
}
}
window.onload = function() { stripedTable(); }
</script>
<style type="text/css">
body {
background: #FFF;
color: #000;
font: normal normal 12px Verdana, Geneva, Arial, Helvetica, sans-serif;
margin: 10px;
padding: 0
}
table, td, a {
color: #000;
font: normal normal 12px Verdana, Geneva, Arial, Helvetica, sans-serif
}
h1 {
font: normal normal 18px Verdana, Geneva, Arial, Helvetica, sans-serif;
margin: 0 0 5px 0
}
h2 {
font: normal normal 16px Verdana, Geneva, Arial, Helvetica, sans-serif;
margin: 0 0 5px 0
}
h3 {
font: normal normal 13px Verdana, Geneva, Arial, Helvetica, sans-serif;
color: #008000;
margin: 0 0 15px 0
}
div.tableContainer {
clear: both;
border: 1px solid #963;
height: 285px;
overflow: auto;
width: 756px
}
html>body div.tableContainer {
overflow: hidden;
width: 756px
}
div.tableContainer table {
float: left;
width: 740px
}
html>body div.tableContainer table {
width: 756px
}
thead.fixedHeader tr {
position: relative
}
html>body thead.fixedHeader tr {
display: block
}
thead.fixedHeader th {
background: #C96;
border-left: 1px solid #EB8;
border-right: 1px solid #B74;
border-top: 1px solid #EB8;
font-weight: normal;
padding: 4px 3px;
text-align: left
}
thead.fixedHeader a, thead.fixedHeader a:link, thead.fixedHeader a:visited {
color: #FFF;
display: block;
text-decoration: none;
width: 100%
}
thead.fixedHeader a:hover {
color: #FFF;
display: block;
text-decoration: underline;
width: 100%
}
html>body tbody.scrollContent {
display: block;
height: 262px;
overflow: auto;
width: 100%
}
tbody.scrollContent td, tbody.scrollContent tr.normalRow td {
background: #FFF;
border-bottom: none;
border-left: none;
border-right: 1px solid #CCC;
border-top: 1px solid #DDD;
padding: 2px 3px 3px 4px
}
tbody.scrollContent tr.alternateRow td {
background: #EEE;
border-bottom: none;
border-left: none;
border-right: 1px solid #CCC;
border-top: 1px solid #DDD;
padding: 2px 3px 3px 4px
}
html>body thead.fixedHeader th {
width: 200px
}
html>body thead.fixedHeader th + th {
width: 240px
}
html>body thead.fixedHeader th + th + th {
width: 316px
}
html>body tbody.scrollContent td {
width: 200px
}
html>body tbody.scrollContent td + td {
width: 240px
}
html>body tbody.scrollContent td + td + td {
width: 300px
}
</style>
</head><body>
<div id="tableContainer" class="tableContainer">
<table border="0" cellpadding="0" cellspacing="0" width="100%" class="scrollTable">
<thead class="fixedHeader">
<tr class="alternateRow">
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tbody class="scrollContent">
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>End of Cell Content 1</td>
<td>End of Cell Content 2</td>
<td>End of Cell Content 3</td>
</tr>
</tbody>
</table>
</div>
</body></html>
I have an idea for you. You will split your table into two tables. One of them will acting as the header and the second will acting as the rest of all cells and rows.
The trick in the following:
Placing two fixed width and height divs vertical adjacent to themselves. the upper one will loads the header table and the n the lower will acts for the table body. in the lower div you will set vertical overflow. By this way you will have simple solution's that supports your header move with data scrolling.
It seems the best way to go about this is two tables. Outer table with headers, and one big row with an inner table inside that. The div should be css'ed overflow: scroll or auto with a set height (via css or javascript). You will have to set specific widths on all the columns. I think the best way to go about that is giving a class for each header, and make sure the corresponding columns in the inner table have the same classes.
<table>
<tr><th>...</th></tr>
<tr><td>
<div><inner table></div>
</td></tr>
</table>
Check this out for examples: http://www.cssplay.co.uk/menu/tablescroll.html
Very quick and sketchy, but hopefully you get the idea, why not just use position:fixed for the thead.
jsfiddle: http://jsfiddle.net/b3S5F/