Printing a table over multiple pages - html

I am doing a project for my employer, and trying to print a large data table over multiple pages for printing purposes.
When I am trying to print the table however, the top borders seem to overlap onto the previous page.
Image preview:
I have tried editing the borders to be different thicknesses, and applying the CSS properties to now allow a to be split over multiple pages, however none of it has had any effect.
Right now I have removed all CSS from the page apart from Bootstrap and the page break rules, but am still having the same issue
My code:
table {
page-break-inside: auto
}
tr {
page-break-inside: avoid;
page-break-after: auto
}
thead {
display: table-header-group
}
tfoot {
display: table-footer-group
}
<table id="test" class="table table-bordered thead-light">
<thead>
<tr>
<th scope="col">Date / Time</th>
<th scope="col">Log Class</th>
<th scope="col">Reason</th>
<th scope="col">Detail</th>
<th scope="col">Hold State</th>
<th scope="col">UL ID</th>
<th scope="col">SKU</th>
<th scope="col">Location</th>
<th scope="col">Destination</th>
<th scope="col">Qty</th>
<th scope="col">User</th>
</tr>
</thead>
<tbody>
Table Data
</tbody>
</table>
I would have expected the borders to remain on the page which the starts, and not clip onto the previous page, however as you can see in the original image, it is still clipping.
Any help would really be appreciated.

I cant understand your real issue but i think you are trying to give different border to th, td then add different class to required one and add border css.
Example:
.border-style {
border:2px solid red !important;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2>Bordered Table</h2>
<p>The .table-bordered class adds borders to a table:</p>
<table class="table table-bordered">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td >Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td class="border-style">Moe</td>
<td>mary#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

I got your issue but not sure why try to inspect that and do a css display:none; if anything on that border
Cant find the issue because i cant inspect on that
Sorry
And check if anywhere you add a display:inline-block i have a issue with this recently

I had this exact problem and unfortunately I didn't find a proper solution - but read on!
The issue seemed to be that the top border from the table header 'leaked' over to the previous page. After some trial an error I found two workarounds (short of deleting the project entirely).
"Solution" #1 - Remove stylings :'(
Removing all borders AND BACKGROUNDS on the top row (including the table border) meant that the leaking pixels are invisible. Hurrah!
#media print {
table, thead tr, thead th {
/* You might not need '!important' with your styling, but
I found with bootstrap that this is the safest option. */
background: none !important;
border: none !important;
}
}
<table class="table table-bordered">
<thead>
<tr>
<th>Awww...</th>
<th>These</th>
<th>are</th>
<th>boring</th>
<th>headers!</th>
</tr>
</thead>
</table>
But while this fixed my issue, it broke my heart. This wasn't the solution I needed...
"Solution" #2 - Hack at it 'till it breaks!
After some considerable crying, I found that I could add another dummy row above my headers and remove the styling on that instead!
"What a terrible solution - thanks Mark!"
th {
border: solid 1px hotpink;
}
#media not print {
.print-only {
display: none;
}
}
<table class="table table-bordered">
<thead>
<!-- This is where the magic is. This row 'pads' the table
headers and keeps them on the same page -->
<tr class="print-only">
<th style="border: none !important; background: none !important;"></th>
</tr>
<tr>
<th>Look</th>
<th>at</th>
<th>these</th>
<th>stylish</th>
<th>headers!</th>
</tr>
</thead>
</table>
So yeah... when one of you coding geniuses (genii?) come across this answer and realize that the rest of us are down shit's creek, please feel free to post a real solution to this headache :)

Related

Text overlapping with CSS transform property

When I am using
.right-align {
text-align: right !important;
transform: translateX(-40%);
}
The Table structure is showing below
<table>
<thead>
<tr>
<th>Bid
</th>
<th>Offer
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="right-align">
200
</div>
</td>
<td>
<div class="right-align">
221
</div>
</td>
</tr>
</tbody>
</table>
The td is overlapping the th element as seen below
How can I can make it go under the header ?
This is happening when table is scrolling
It is very hard to answer the question as it is, however, the table should keep its proportions and structure as long as you keep the code tight:
.right-align {
text-align: right !important;
}
<table>
<thead>
<tr>
<th>Bid</th>
<th>Offer</th>
</tr>
</thead>
<tbody>
<tr>
<td class="right-align">200</td>
<td class="right-align">221</td>
</tr>
</tbody>
</table>
It is nebulous why you decided to use the transform: translateX(-40%); rule in there, but it seems you may be trying to overwrite some rules that come from a theme hence the problem you are facing; If you update your question and add more pieces of code or at least what you are trying to achieve then i could be more helpful :). Also if you are using a framework or theme specify which one.
EDIT.
I saw your updates, you don't need to add a div within the td element to apply a class, you can do it directly in the td element. However, it seems that some css rules are overlapping. Maybe a screenshot of the results in a browser could be helpful.

Contextual Classes cannot override Table Head Colors Classes (.thead-dark/.thead-light)

I am studying tables in Bootstrap 4.
I don't know why the background-color in table-light class is not applied. Is this because table-light cannot override the thead-dark? If it is true, can you tell me what makes thead-dark take priority over? If it is not what I think, please explain the reason behind it for me.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<link href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet">
<title>Table</title>
</head>
<body>
<div class="container">
<h2>Contextual Classes</h2>
<p>Contextual classes can be used to color the table, table rows or table cells. The classes that can be used are: .table-primary, .table-success, .table-info, .table-warning, .table-danger, .table-active, .table-secondary, .table-light and .table-dark:</p>
<table class="table">
<thead class="thead-dark">
<tr>
<th class="table-light">Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>Default</td>
<td>Defaultson</td>
<td>def#somemail.com</td>
</tr>
<tr class="table-primary">
<td>Primary</td>
<td>Joe</td>
<td>joe#example.com</td>
</tr>
<tr class="table-success">
<td>Success</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr class="table-danger">
<td>Danger</td>
<td>Moe</td>
<td>mary#example.com</td>
</tr>
<tr class="table-info">
<td>Info</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
<tr class="table-warning">
<td>Warning</td>
<td>Refs</td>
<td>bo#example.com</td>
</tr>
<tr class="table-active">
<td>Active</td>
<td>Activeson</td>
<td>act#example.com</td>
</tr>
<tr class="table-secondary">
<td>Secondary</td>
<td>Secondson</td>
<td>sec#example.com</td>
</tr>
<tr class="table-light">
<td>Light</td>
<td>Angie</td>
<td>angie#example.com</td>
</tr>
<tr class="table-dark text-dark">
<td>Dark</td>
<td>Bo</td>
<td>bo#example.com</td>
</tr>
</tbody>
</table>
</div>
</body> <!-- source: https://www.w3schools.com/bootstrap4/bootstrap_tables.asp -->
Problem:
This is how .thead-light is defined in the Bootstrap stylesheet.
.table .thead-light th {
color: #495057;
background-color: #e9ecef;
border-color: #dee2e6;
}
You see it targets th elements which are descendants of an element which has the thead-light class.
So when you apply the class to a th element, as you do in
<th class="table-light">Firstname</th>
you would need to target
th.thead-light {
/* CSS */
}
Otherwise the specificity of .table-dark > th will override that of <th class="table-light">
.table-dark,
.table-dark > th, /* <<< This rule */
.table-dark > td {
background-color: #c6c8ca;
}
In the bootstrap.css this rule:
.table .thead-dark th {
color: #fff;
background-color: #212529;
border-color: #32383e;
}
is defined after this rule:
.table-light,
.table-light > th,
.table-light > td {
background-color: #fdfdfe;
}
But most importantly:
When you use the CSS Specificity Calculator and compare this:
th.table-light (which is what's actually being used here) to this .table .thead-dark th, you'll see that the latter has higher specificity and thus wins regardless.
Conclusion:
In order for a css rule to "win" (i.e. take precedence) it must either have higher specificity than a competing css rule OR if the specificity is the same (which is not the case here), it must be listed after the competing css rule.
Also note:
Using the !important flag (as some people might suggest) should only be reserved for quick testing and should not be used as a permanent solution. (because otherwise, it would result in a nightmare for maintenance)

Page break only between tbody when printing from Chrome

I have a <table> of data where consecutive rows are conceptually related and need to stay together. I've group each pair of rows in a <tbody> tag. When it comes time to print the table, I want to make sure that page breaks only happen between <tbody> tags.
I've tried some variations of page-break-inside: avoid and page-break-after: auto, but can't seem to get it to work in Chrome 42 (see screenshot below)
However, it does seems to work as expected in Firefox 40 and IE 11 though. It looks like page-break-* might only apply to block level elements. Is there a good way to accomplish this in html/css?
Example code:
<!doctype html>
<html>
<head>
<style>
table {
width: 70%;
border-collapse: collapse;
}
thead {
display: table-header-group;
text-align: left;
border-bottom: 2px solid #000;
}
tbody {
page-break-inside: avoid;
border-bottom: 1px solid #ccc;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>Project #</th>
<th>Owner</th>
<th>% Complete</th>
</tr>
</thead>
<tbody>
<tr>
<td>HR-123</td>
<td>Arther Dent</td>
<td>42%</td>
</tr>
<tr>
<td colspan='3'>Description: Find travel guide to get me back to earth.</td>
</tr>
</tbody>
<tbody>
<tr>
<td>RD-123</td>
<td>Frodo Baggins</td>
<td>9%</td>
</tr>
<tr>
<td colspan='3'>Description: Find a better way to get the ring to Mordor.</td>
</tr>
</tbody>
<!-- repeat tbody sections as necessary to get onto the second page -->
</table>
</body>
</html>
Here's a JSFiddle that'll give you a bit of an idea of what I'm trying to accomplish.
Edit: I considering not using a table but didn't since (i) I want my columns to line up, and (ii) I really don't want to hard-code column widths to make sure they're all the same.
Try wrapping it all in a
make that specific a block element (http://learnlayout.com/inline-block.html)
then use page-break-*

Column width for <th> not working

Here is my html:
<html>
<head>
<meta charset="utf-8">
<link href="css/bootstrap.css" rel="stylesheet">
<link href="css/bootstrap-theme.css" rel="stylesheet">
</head>
<body style="padding-top: 47px;">
<table class="table table-hover table-striped-custom">
<thead>
<tr>
<th style="width: 5px;"></th>
<th>Column2</th>
<th>column2</td>
</tr>
</thead>
<tbody>
<tr>
<td style="background-color: #FF5F5F;width: 5px;"></td>
<td>blaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</td>
<td>bla</td>
</tr>
<tr>
<td style="background-color: deepskyblue"></td>
<td>bla</td>
<td>bla</td>
</tr>
</tbody>
</table>
Problem is when setting width for first column: it won't go under 16px. If I put bigger width(20,50), colored column become larger, but when I try to set them thinner (for example 7px), It doesn't take any effect.
How can I do it, without removing any css class from existing template. Colored column have to be first, it's height must be as row's height and I have to be able to set it's width to any value I want.
It's because your bootstrap css is adding 8px padding to the table cells (which is why your min width is 16px: 8px left plus 8px right) - try adding padding:0; for those cells and it should work
Example
It's possible that bootstrap has set min-width on th or td. If so, I'd add an additional style block (in the HTML, if you can't add/edit external CSS), to allow the first column to be as small as you like:
<style type="text/css">
.table td:first-child, .table th:first-child {
min-width: 0;
padding: 0;
}
</style>

HTML table headers always visible at top of window when viewing a large table

I would like to be able to "tweak" an HTML table's presentation to add a single feature: when scrolling down through the page so that the table is on the screen but the header rows are off-screen, I would like the headers to remain visible at the top of the viewing area.
This would be conceptually like the "freeze panes" feature in Excel. However, an HTML page might contain several tables in it and I only would want it to happen for the table that is currently in-view, only while it is in-view.
Note: I've seen one solution where the table data area is made scrollable while the headers do not scroll. That's not the solution I'm looking for.
Check out jQuery.floatThead (demos available) which is very cool, can work with DataTables too, and can even work inside an overflow: auto container.
Craig, I refined your code a bit (among a few other things it's now using position:fixed) and wrapped it as a jQuery plugin.
Try it out here: http://jsfiddle.net/jmosbech/stFcx/
And get the source here: https://github.com/jmosbech/StickyTableHeaders
If you're targeting modern css3 compliant browsers (Browser support: https://caniuse.com/#feat=css-sticky) you can use position:sticky, which doesn't require JS and won't break the table layout miss-aligning th and td of the same column. Nor does it require fixed column width to work properly.
Example for a single header row:
thead th
{
position: sticky;
top: 0px;
}
For theads with 1 or 2 rows, you can use something like this:
thead > :last-child th
{
position: sticky;
top: 30px; /* This is for all the the "th" elements in the second row, (in this casa is the last child element into the thead) */
}
thead > :first-child th
{
position: sticky;
top: 0px; /* This is for all the the "th" elements in the first child row */
}
You might need to play a bit with the top property of the last child changing the number of pixels to match the height of the first row (+ the margin + the border + the padding, if any), so the second row sticks just down bellow the first one.
Also both solutions work even if you have more than one table in the same page: the th element of each one starts to be sticky when its top position is the one indicated into the css definition and just disappear when all the table scrolls down. So if there are more tables all work beautifully the same way.
Why to use last-child before and first-child after in the css?
Because css rules are rendered by the browser in the same order as you write them into the css file and because of this if you have just 1 row into the thead element the first row is simultaneously the last row too and the first-child rule need to override the last-child one. If not you will have an offset of the row 30 px from the top margin which I suppose you don't want to.
A known problem of position: sticky is that it doesn't work on thead elements or table rows: you must target th elements. Hopping this issue will be solved on future browser versions.
The most simple answer only using CSS :D !!!
table {
/* Not required only for visualizing */
border-collapse: collapse;
width: 100%;
}
table thead tr th {
/* you could also change td instead th depending your html code */
background-color: green;
position: sticky;
z-index: 100;
top: 0;
}
td {
/* Not required only for visualizing */
padding: 1em;
}
<table>
<thead>
<tr>
<th>Col1</th>
<th>Col2</th>
<th>Col3</th>
</tr>
</thead>
<tbody>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>david</td>
<td>castro</td>
<td>rocks!</td>
</tr>
</tbody>
</table>
Possible alternatives
js-floating-table-headers
js-floating-table-headers (Google Code)
In Drupal
I have a Drupal 6 site. I was on the admin "modules" page, and noticed the tables had this exact feature!
Looking at the code, it seems to be implemented by a file called tableheader.js. It applies the feature on all tables with the class sticky-enabled.
For a Drupal site, I'd like to be able to make use of that tableheader.js module as-is for user content. tableheader.js doesn't seem to be present on user content pages in Drupal. I posted a forum message to ask how to modify the Drupal theme so it's available. According to a response, tableheader.js can be added to a Drupal theme using drupal_add_js() in the theme's template.php as follows:
drupal_add_js('misc/tableheader.js', 'core');
I've encountered this problem very recently. Unfortunately, I had to do 2 tables, one for the header and one for the body. It's probably not the best approach ever but here goes:
<html>
<head>
<title>oh hai</title>
</head>
<body>
<table id="tableHeader">
<tr>
<th style="width:100px; background-color:#CCCCCC">col header</th>
<th style="width:100px; background-color:#CCCCCC">col header</th>
</tr>
</table>
<div style="height:50px; overflow:auto; width:250px">
<table>
<tr>
<td style="height:50px; width:100px; background-color:#DDDDDD">data1</td>
<td style="height:50px; width:100px; background-color:#DDDDDD">data1</td>
</tr>
<tr>
<td style="height:50px; width:100px; background-color:#DDDDDD">data2</td>
<td style="height:50px; width:100px; background-color:#DDDDDD">data2</td>
</tr>
</table>
</div>
</body>
</html>
This worked for me, it's probably not the elegant way but it does work. I'll investigate so see if I can do something better, but it allows for multiple tables.
Go read on the overflow propriety to see if it fits your need
Using display: fixed on the thead section should work, but for it only work on the current table in view, you will need the help of JavaScript. And it will be tricky because it will need to figure out scrolling places and location of elements relative to the viewport, which is one of the prime areas of browser incompatibility.
Have a look at the popular JavaScript frameworks (jQuery, MooTools, YUI, etc etc.) to see if they can either do what you want or make it easier to do what you want.
If you use a full screen table you are maybe interested in setting th to display:fixed; and top:0; or try a very similar approach via css.
Update
Just quickly build up a working solution with iframes (html4.0). This example IS NOT standard conform, however you will easily be able to fix it:
outer.html
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Outer</title>
<body>
<iframe src="test.html" width="200" height="100"></iframe>
</body>
</html>
test.html
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Floating</title>
<style type="text/css">
.content{
position:relative;
}
thead{
background-color:red;
position:fixed;
top:0;
}
</style>
<body>
<div class="content">
<table>
<thead>
<tr class="top"><td>Title</td></tr>
</head>
<tbody>
<tr><td>a</td></tr>
<tr><td>b</td></tr>
<tr><td>c</td></tr>
<tr><td>d</td></tr>
<tr><td>e</td></tr>
<tr><td>e</td></tr>
<tr><td>e</td></tr>
<tr><td>e</td></tr>
<tr><td>e</td></tr>
<tr><td>e</td></tr>
</tbody>
</table>
</div>
</body>
</html>
This is really a tricky thing to have a sticky header on your table. I had same requirement but with asp:GridView and then I found it really thought to have sticky header on gridview. There are many solutions available and it took me 3 days trying all the solution but none of them could satisfy.
The main issue that I faced with most of these solutions was the alignment problem. When you try to make the header floating, somehow the alignment of header cells and body cells get off track.
With some solutions, I also got issue of getting header overlapped to first few rows of body, which cause body rows getting hidden behind the floating header.
So now I had to implement my own logic to achieve this, though I also not consider this as perfect solution but this could also be helpful for someone,
Below is the sample table.
<div class="table-holder">
<table id="MyTable" cellpadding="4" cellspacing="0" border="1px" class="customerTable">
<thead>
<tr><th>ID</th><th>First Name</th><th>Last Name</th><th>DOB</th><th>Place</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>Customer1</td><td>LastName</td><td>1-1-1</td><td>SUN</td></tr>
<tr><td>2</td><td>Customer2</td><td>LastName</td><td>2-2-2</td><td>Earth</td></tr>
<tr><td>3</td><td>Customer3</td><td>LastName</td><td>3-3-3</td><td>Mars</td></tr>
<tr><td>4</td><td>Customer4</td><td>LastName</td><td>4-4-4</td><td>Venus</td></tr>
<tr><td>5</td><td>Customer5</td><td>LastName</td><td>5-5-5</td><td>Saturn</td></tr>
<tr><td>6</td><td>Customer6</td><td>LastName</td><td>6-6-6</td><td>Jupitor</td></tr>
<tr><td>7</td><td>Customer7</td><td>LastName</td><td>7-7-7</td><td>Mercury</td></tr>
<tr><td>8</td><td>Customer8</td><td>LastName</td><td>8-8-8</td><td>Moon</td></tr>
<tr><td>9</td><td>Customer9</td><td>LastName</td><td>9-9-9</td><td>Uranus</td></tr>
<tr><td>10</td><td>Customer10</td><td>LastName</td><td>10-10-10</td><td>Neptune</td></tr>
</tbody>
</table>
</div>
Note: The table is wrapped into a DIV with class attribute equal to 'table-holder'.
Below is the JQuery script that I added in my html page header.
<script src="../Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="../Scripts/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
//create var for table holder
var originalTableHolder = $(".table-holder");
// set the table holder's with
originalTableHolder.width($('table', originalTableHolder).width() + 17);
// Create a clone of table holder DIV
var clonedtableHolder = originalTableHolder.clone();
// Calculate height of all header rows.
var headerHeight = 0;
$('thead', originalTableHolder).each(function (index, element) {
headerHeight = headerHeight + $(element).height();
});
// Set the position of cloned table so that cloned table overlapped the original
clonedtableHolder.css('position', 'relative');
clonedtableHolder.css('top', headerHeight + 'px');
// Set the height of cloned header equal to header height only so that body is not visible of cloned header
clonedtableHolder.height(headerHeight);
clonedtableHolder.css('overflow', 'hidden');
// reset the ID attribute of each element in cloned table
$('*', clonedtableHolder).each(function (index, element) {
if ($(element).attr('id')) {
$(element).attr('id', $(element).attr('id') + '_Cloned');
}
});
originalTableHolder.css('border-bottom', '1px solid #aaa');
// Place the cloned table holder before original one
originalTableHolder.before(clonedtableHolder);
});
</script>
and at last below is the CSS class for bit of coloring purpose.
.table-holder
{
height:200px;
overflow:auto;
border-width:0px;
}
.customerTable thead
{
background: #4b6c9e;
color:White;
}
So the whole idea of this logic is to place the table into a table holder div and create clone of that holder at client side when page loaded. Now hide the body of table inside clone holder and position the remaining header part over to original header.
Same solution also works for asp:gridview, you need to add two more steps to achieve this in gridview,
In OnPrerender event of gridview object in your web page, set the table section of header row equal to TableHeader.
if (this.HeaderRow != null)
{
this.HeaderRow.TableSection = TableRowSection.TableHeader;
}
And wrap your grid into <div class="table-holder"></div>.
Note: if your header has clickable controls then you may need to add some more jQuery script to pass the events raised in cloned header to original header. This code is already available in jQuery sticky-header plugin create by jmosbech
It's frustrating that what works great in one browser doesn't work in others. The following works in Firefox, but not in Chrome or IE:
<table width="80%">
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
<tbody style="height:50px; overflow:auto">
<tr>
<td>Cell A1</td>
<td>Cell B1</td>
<td>Cell C1</td>
</tr>
<tr>
<td>Cell A2</td>
<td>Cell B2</td>
<td>Cell C2</td>
</tr>
<tr>
<td>Cell A3</td>
<td>Cell B3</td>
<td>Cell C3</td>
</tr>
</tbody>
</table>