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/
Related
I have a table, when I add a row to it, the row's height will fill the whole body of the table. I want to force the height to only be around 10% of the tables body height, and let the rest of the tabe body to be empty. I've tried adding a height propery of 10% to the tbody tr selector but nothing happens. My goal is to have a row take up about 10% of the open area, and then when I click add row, another one will appear under it until the whole table body is full of rows.
Here is my code
#home-index {
margin-top: 10px;
}
tbody {
height: 604px;
}
td {
border: 1px solid lightgray;
}
.hours-cell:hover {
background-color: darkorange;
}
tr {
border: 1px solid lightgray;
}
th {
border: 1px solid lightgray;
}
.dropdown {
width: 25%
}
<table>
<thead>
<tr>
<th>Project</th>
<th>Task</th>
<th>7/11</th>
<th>7/12</th>
<th>7/13</th>
<th>Total Hours</th>
</tr>
</thead>
<tbody>
<tr>
<td class="dropdown">
<select asp-for="Project" asp-items="Model.Projects"></select>
</td>
<td class="dropdown">
<select asp-for="Task"></select>
</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Overall Totals</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td></td>
</tr>
<tr>
<td colspan="2">Over/Under</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td></td>
</tr>
</tfoot>
</table>
I hope this helps your problem. I added an empty <tr> at the very end of the body with a different class. You can style this row however you like to make it look like an empty body. Any rows you add should be added above this one.
#home-index {
margin-top: 10px;
}
tbody {
height: 604px;
}
td {
border: 1px solid lightgray;
}
.hours-cell:hover {
background-color: darkorange;
}
tr {
border: 1px solid lightgray;
}
th {
border: 1px solid lightgray;
}
.dropdown {
width: 25%
}
tbody tr {
height: 10%
}
.extra {
height: 100%
}
<table>
<thead>
<tr>
<th>Project</th>
<th>Task</th>
<th>7/11</th>
<th>7/12</th>
<th>7/13</th>
<th>Total Hours</th>
</tr>
</thead>
<tbody>
<tr>
<td class="dropdown">
<select asp-for="Project" asp-items="Model.Projects"></select>
</td>
<td class="dropdown">
<select asp-for="Task"></select>
</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td></td>
</tr>
<tr class="extra">
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Overall Totals</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td></td>
</tr>
<tr>
<td colspan="2">Over/Under</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td class="hours-cell">--</td>
<td></td>
</tr>
</tfoot>
</table>
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 have one table in that I am repeating data inside column. One column have property and other have value of that property. I am getting problem when data wraps property and value not aligned properly. Below is my example.
My example
<table cellspacing="0" celpadding="0">
<thead>
<tr>
<th>Property</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div>Property 1</div>
<div>Property 2</div>
<div>Property 3</div>
<div>Property 4</div>
</td>
<td>
<div>Value 1</div>
<div>Value 2</div>
<div>Value 3</div>
<div>Value 4</div>
</td>
</tr>
<tr>
<td>Property 2</td>
<td>Value 2</td>
</tr>
<tr>
<td>Property 1</td>
<td>Property 1</td>
</tr>
</tbody>
</table>
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
color:#fff;
}
table{
width:100px
}
table tr td,table tr th{border:1px solid #fff;padding:5px;}
table tr td div{
border-bottom:1px solid #eee;
padding:5px 0;
}
Right now I have given fixed width to table to produce my problem. In this condition what should I do to reolve this issue. I want to align property and value equally with respective values. Please help.
The easiest way to solve your issue is to add a fixed height to your table tr td div rules, so that it aligns properly. So, you could update that specific rule to something like:
table tr td div{
border-bottom: 1px solid #eee;
padding: 5px 0;
height: 48px;
}
However, <div>s are not really supposed to go into tables. Maybe you need to rethink your table's structure, as this will have accessibility issues for sure.
What's wrong with using a classic table with no random divs contained in your td elements? Consider the below:
<table cellspacing="0">
<tr>
<td>Property 1</td>
<td>Value 1</td>
</tr>
<tr>
<td>Property 2</td>
<td>Value 2</td>
</tr>
<tr>
<td>Property 3</td>
<td>Value 3</td>
</tr>
<tr>
<td>Property 4</td>
<td>Value 4</td>
</tr>
</table>
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
color:#fff;
}
table{
width:200px
}
td {
width:100px;
padding:10px;
border:1px solid white;
}
Here is a fiddle: https://jsfiddle.net/8dyxqbkz/2/
You should use <tr><tr/> tag for table row
and <td><td/> tag for table cell.
Let me show an example:
<table cellspacing="0" celpadding="0">
<tr>
<td>
Property 1
</td>
<td>
Property 2
</td>
<td>
Property 3
</td>
<td>
Property 4
</td>
</tr>
<tr>
<td>Value 1</td>
<td>Value 2</td>
<td>Value 3</td>
<td>Value 4</td>
</tr>
<tr>
<td>Property 2</td>
<td>Property 1</td>
</tr>
<tr>
<td>Value 2</td>
<td>Property 1</td>
</tr>
</table>
This is my table html I am trying to How to include 2 columns under one column header using Jquery I tried this code:
$('#test th.column_Column1').append( $('<th/>', {text : 'HEADER BOth'}) );
But it doesn't give the desired output:
<table class="xrounded_shadowed default footable-loaded footable" id="test">
<thead>
<tr>
<th class="select_checkbox footable-visible footable-first-column" style="width: 40px;"><label><input type="checkbox" onclick="toggleAll(this)" style="float:left;"><i></i></label></th>
<th class="column_Column1 footable-visible">Column1</th>
<th class="column_Column2 footable-visible footable-last-column">Hari</th></tr></thead>
<tbody>
<tr class="odd">
<td class="select_checkbox footable-visible footable-first-column"><label><input type="checkbox" name="d-49700-checkbox_username" value=""><i></i></label></td>
<td class="column_Column1 footable-visible" style=""><span class="footable-toggle"></span>01/01/2019</td>
<td class="column_Column2 footable-visible footable-last-column" style="">Tuesday</td></tr>
<tr class="even">
<td class="select_checkbox footable-visible footable-first-column"><label><input type="checkbox" name="d-49700-checkbox_username" value=""><i></i></label></td>
<td class="column_Column1 footable-visible" style=""><span class="footable-toggle"></span>01/01/2019</td>
<td class="column_Column2 footable-visible footable-last-column" style="">Tuesday</td></tr>
<tr class="odd">
<td class="select_checkbox footable-visible footable-first-column"><label><input type="checkbox" name="d-49700-checkbox_username" value=""><i></i></label></td>
<td class="column_Column1 footable-visible" style=""><span class="footable-toggle"></span>01/01/2019</td>
<td class="column_Column2 footable-visible footable-last-column" style="">Tuesday</td></tr>
<tr class="even">
<td class="select_checkbox footable-visible footable-first-column"><label><input type="checkbox" name="d-49700-checkbox_username" value=""><i></i></label></td>
<td class="column_Column1 footable-visible" style=""><span class="footable-toggle"></span>01/01/2019</td>
<td class="column_Column2 footable-visible footable-last-column" style="">Tuesday</td></tr>
<tr class="odd">
<td class="select_checkbox footable-visible footable-first-column"><label><input type="checkbox" name="d-49700-checkbox_username" value=""><i></i></label></td>
<td class="column_Column1 footable-visible" style=""><span class="footable-toggle"></span>01/01/2019</td>
<td class="column_Column2 footable-visible footable-last-column" style="">Tuesday</td></tr></tbody></table>
Add two rows instead and the first one should have one single column that spans across all columns
<table>
<thead>
<tr>
<th colSpan="2">Column Header</th>
</tr>
<tr>
<th>Column 1</th>
<th>Column 2</th>
</tr>
</thead>
</table>
Here's a snippet with more details using jQuery to do it dynamically...
$(function(){
var $thead = $("<thead></thead>");
$thead.append("<tr><th colspan='2'>Column Header</th></tr>");
$thead.append("<tr><th>Column1</th><th>Column2</th></tr>");
$("table").append($thead);
});
table{
width: 100%;
border-collapse: collapse;
border: 1px solid #333;
}
thead{
background-color: #FFEB3B;
}
th, td{
border: 1px solid #333;
padding:4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<table>
</table>
The colSpan and rowSpan attribute is used to do such kind of things.In this case use need to use colSpan to ur <th>. And then set its text-align:center and you will be done
th:nth-child(1) {
text-align: center;
}
th,td{
border:2px solid
}
table{
border-collapse:collapse;
}
<table>
<thead>
<tr>
<th colSpan="2">Column Header</th>
</tr>
<tr>
<th>Column 1</th>
<th>Column 2</th>
</tr>
<tbody>
<tr>
<td>Column 1 Item</td>
<td>Column 2 Item</td>
</tr>
<tr>
<td>Column 1 Item</td>
<td>Column 2 Item</td>
</tr>
</tbody>
</thead>
</table>
I am having an issue getting the tr to change the border when it has a nested table. Can someone help me out with this.
Here is my table structure
<table class="SearchResults" cellpadding="0" cellspacing="0" id="tblResultsHTML">
<tbody>
<tr class="BlackHeader">
<td>header here</td>
</tr>
<tr>
<td>
<table class="SearchResults" cellpadding="2" cellspacing="0" width="100%">
<tbody>
<tr class="GroupHeader">
<td>group 1</td>
</tr>
<tr>
<td width="75%">sub 1</td>
<td valign="top">sub 2</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<table class="SearchResults" cellpadding="2" cellspacing="0" width="100%">
<tbody>
<tr class="GroupHeader">
<td>group 2</td>
</tr>
<tr>
<td width="75%">sub 1</td>
<td valign="top">sub 2</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
my jquery which worked when i didn't have nested tables is this
$('#tblResultsHTML').live("mouseover mouseout", function (event) {
if (event.type == "mouseover") {
$(this).contents('td').css({ 'border': '2px solid black', 'border-left': 'none', 'border-right': 'none' });
$(this).contents('td:first').css('border-left', '2px solid black');
$(this).contents('td:last').css('border-right', '2px solid black');
} else {
$(this).contents('td').css('border', 'none');
}
});
What I want to happen is that the whole row containing the nested table has a border when I hover it. So if I put the mouse over group 1, the whole nested table in that row will have a border. Does this make sense??
Thanks
http://jsfiddle.net/dQgXF/2/
Remove the "SearchResults" class from your outer table and try this JS:
$('.SearchResults').live(
{
mouseover: function() {
$(this).parent().css({
border:'2px solid black',
});
},
mouseout: function() {
$(this).parent().css({
border:0,
});
},
});