Ask Ben: Optimizing Tables For Printing

Posted September 12, 2008 at 10:29 AM

Tags: HTML / CSS, Ask Ben

Hey I have a report I want to print but keep the header on every page, column names. Any suggestions?

HTML table elements are actually designed to allow for this very functionality. The trick is that you have to use the THEAD tag which defines the table header. By using the THEAD tag, the rows that you define within the THEAD tag will be displayed at the top of every printed page. Additionally, you can use the TFOOT tag to define the table footer. By using the TFOOT tag, the rows that you define within the TFOOT tag will be displayed at the bottom of every page.

Let's take a look at some sample HTML that has a long table that makes use of both the THEAD and TFOOT HTML tags:

 Launch code in new window » Download code as text file »

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>Table Printing Demo</title>
  •  
  • <style type="text/css">
  •  
  • body {
  • font-family: verdana, arial, sans-serif ;
  • font-size: 12px ;
  • }
  •  
  • th,
  • td {
  • padding: 4px 4px 4px 4px ;
  • text-align: center ;
  • }
  •  
  • th {
  • border-bottom: 2px solid #333333 ;
  • }
  •  
  • td {
  • border-bottom: 1px dotted #999999 ;
  • }
  •  
  • tfoot td {
  • border-bottom-width: 0px ;
  • border-top: 2px solid #333333 ;
  • padding-top: 20px ;
  • }
  •  
  • </style>
  •  
  • </head>
  • <body>
  •  
  • <cfoutput>
  •  
  • <h1>
  • Table Print Demonstration
  • </h1>
  •  
  • <p>
  • This demonstrates how to properly define an HTML table
  • in such a way that it will display the table header on
  • each of the printed pages.
  • </p>
  •  
  •  
  • <table
  • cellspacing="0"
  • summary="This is a really long table that is used to demonstrate the print of headers across several pages.">
  •  
  • <!---
  • Define the HEAD of the table. This is the data that
  • will be displayed at the top of every printed page.
  • --->
  • <thead>
  • <tr>
  • <th>
  • ID
  • </th>
  • <th>
  • Value
  • </th>
  • </tr>
  • </thead>
  •  
  • <!---
  • Defint eh FOOTER of the table. This is the data that
  • will be displayed at the bottom of every printed page.
  • --->
  • <tfoot>
  • <tr>
  • <td colspan="2">
  • Kinky Solutions Table Demo
  • </td>
  • </tr>
  • </tfoot>
  •  
  • <!--- Define the BODY of the table. This is the data. --->
  • <tbody>
  •  
  • <!---
  • Let's now create a ton or rows that will require
  • several pages to fully print.
  • --->
  • <cfloop
  • index="intRow"
  • from="1"
  • to="100"
  • step="1">
  •  
  • <tr>
  • <td>
  • #intRow#
  • </td>
  • <td>
  • #RandRange( 111111, 999999 )#
  • </td>
  • </tr>
  •  
  • </cfloop>
  •  
  • </tbody>
  • </table>
  •  
  • </cfoutput>
  •  
  • </body>
  • </html>

Now, when we go to view the print preview of the page, this is what we get:


 
 
 

 
Table Header And Footer Gets Printed On All Pages When You Use The THEAD and TFOOT Tags Respectively.  
 
 
 

Notice that the header and footer data of the table are displayed on all pages that are required to print the table data.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page



Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Sep 12, 2008 at 2:20 PM // reply »
8 Comments

How would you put this into a PDF with the styles working?


Sep 12, 2008 at 3:52 PM // reply »
6,516 Comments

@B,

You should just be able to wrap this in a CFDocument tag, but I have not test that. I can see if I carve out a few minutes.


Sep 12, 2008 at 4:12 PM // reply »
177 Comments

What, no sexy tbody?!


Sep 12, 2008 at 4:20 PM // reply »
6,516 Comments

@Todd,

She's there, I just felt her goodness was implicit enough that it didn't need mention :)


Sep 12, 2008 at 4:22 PM // reply »
177 Comments

But, but... I was looking forward to a saucy tbody!!


Sep 12, 2008 at 4:27 PM // reply »
6,516 Comments

@Todd,

Oh man, I didn't even think of that! My brain is slacking! Maybe when I start to mess with the PDF version ;)


Sep 12, 2008 at 4:51 PM // reply »
8 Comments

Ya the PDF version will do that to ya


Sep 12, 2008 at 7:44 PM // reply »
27 Comments

How come CFTABLE doesn't do that? :)

I had high hopes for CFTABLE, but every time I use it, my boss will ask me to give him strip colour...

Bam! back to reality.

Then I'll have to go back to the good old CFOUTPUT... until CSS3 is available or use jQuery.


Sep 12, 2008 at 7:51 PM // reply »
177 Comments

People still use CFTABLE? o_O


Sep 14, 2008 at 11:19 AM // reply »
1 Comments

To me, the TABLE element is a constant source of surprises ;-) Until recently, I was not aware of the COL element for instance which allows a great deal of flexible styling and markup with touching individual table cells.


Sep 15, 2008 at 8:55 AM // reply »
6,516 Comments

@Robert,

I am a big fan of the COL tag to define column widths, but I have had some trouble getting it to work with other styles. What kind of styles are you finding work nicely?


Sep 15, 2008 at 9:36 AM // reply »
16 Comments

Now if only IE would support these tags properly. (I'm the millionth person to post that sentence - I win!)

I'm currently working on migrating a bunch of reports from Access (don't ask) to CF. One of them displays information for a bunch of different vendors, a couple of pages per vendor, and shows vendor name and phone number in the page footer.

Using TFOOT puts me closer than anything else I've tried: in Firefox, the footer is displayed at the bottom of all pages but the last for each vendor, which is fine. (On the last vendor page, it's displayed at the bottom of the content.) Unfortunately, there are very few people here who use Firefox, so my solutions have to work in IE. :(

Oh yes, did I mention that the intranet (where the reports are housed) is currently running on MX 6?

Hopefully I will get some time soon to start moving our sites to CF 8 ... at the last place I worked, we didn't even use 6, just went straight from 5 to MX 7 ...


Sep 15, 2008 at 9:47 AM // reply »
6,516 Comments

@Dave,

Oh my god! I feel like such an idiot. Can you believe that I didn't even test this solution in Internet Explorer (IE). For some reason, I just assumed that the way tables were handled when printing was handled the same across all browsers. I guess, I just categorized it as part of the print driver or something.

But, I just tested the above in IE7, and you are correct - this doesn't work at all. Lame!!!


Sep 15, 2008 at 9:55 AM // reply »
6,516 Comments

I just tried this with CFDocument as well and I am disappointed to report that the PDF does not print the table header properly either! Not cool :(


Sep 15, 2008 at 10:33 AM // reply »
16 Comments

@Ben,

I can believe it ... I've run into something similar two or three times already on this project. Usually it's been when my boss asked how a report was coming along, and I showed him in Firefox. We open IE aaaaand it's back to the drawing board.

Maybe IE 8 will reach the same level of CSS compliance as Firefox ... I'd try the beta but I'm afraid of it. :)


Sep 17, 2008 at 2:26 PM // reply »
3 Comments

i just came across this. i'd seen people use thead before, but i didn't see the point. i was excited to go out and try it. started testing.. not only does it not work in ie, but it appears this is simply a ff feature. opera, safari and chrome don't seem to do this operation either... it is a nice feature though.


Sep 18, 2008 at 12:16 AM // reply »
2 Comments

Man, that scared me a bit. I thought I had been missing something all this time that would've been real useful. What a relief to realize I hadn't. I just googled THEAD and saw you can use this: <style> thead { display: table-header-group; } </style>. But then IE doesn't break the table cleanly - you get vertical lines that have been cut off halfway. Of course a workaround in CF is to use <cfsavecontent variable="tableHeader"><tr><th>Col1</th><th>Col2</th></cfsavecontent>, count lines, close your table, then insert a page break - <p style="page-break-after: always; color:white;">.</p>


Sep 18, 2008 at 7:50 AM // reply »
16 Comments

The problem with that workaround in my case is that I have several fields that are basically memo/text/clob fields, so I can't even be sure how many lines I'm displaying on a "page", and there's one particular section of the report that can be repeated often enough that it might take up more than one page on its own ...

Well, okay, actually the problem in my case is that we're trying to take a report that was designed specifically for Access and preserve the appearance but also make it look good as an HTML report printed on paper. :)


Sep 18, 2008 at 8:23 AM // reply »
6,516 Comments

I feel bad - that I thought this stuff was all cross-browser. I didn't mean to mislead or panic anyone.

... however, let's not forget that using THEAD and TFOOT does have a number of benefits! For starters, it's simply good, semantic HTML. But, more than that, using THEAD and TFOOT gives us many CSS hooks to help style our tables without additional class names.


Sep 18, 2008 at 1:02 PM // reply »
8 Comments

I ended up going back to font= and basic table tags to get pages to display across browser type and print with header and footer.

Works well enough.


Sep 18, 2008 at 1:03 PM // reply »
8 Comments

Oh and using cfdocument


Sep 18, 2008 at 4:44 PM // reply »
3 Comments

not to mention you can use jquery to sort the columns in the dom rather than another page request. you have to use the thead, th, tbody of the table. working on something in that now.


Sep 18, 2008 at 7:03 PM // reply »
2 Comments

@Dave

For memo/text/clob/etc fields, you can determine the number of characters in the data, estimate the number of characters per line and calculate when to break a page. Of course with most fonts that will only be an estimate, as some letters (ie, WWWWW) would be longer than others (ie, IIIII). There are fixed-width fonts like Courier New, that if you're users don't mind the look of them, would allow you to calculate exactly when to break a page. Oh, one other thing, in the table style I fix the width in centimeters (rather than px, em, etc) b/c that seems to work across different PCs and printers in IE (not sure of the other browsers). 17.5cm for portrait and 23.5cm for landscape. Eg., <table style="width:17.5cm;">.

@Ben

No worries.


Sep 19, 2008 at 8:04 AM // reply »
16 Comments

@Ray

It's true, I could probably fake a page footer by tracking the approximate position on the page and inserting whatever would be necessary to put a div with my "page footer" near the bottom of each page, with a break to follow ... I've done stuff like that in Excel before for similar reasons (long report sections that people wanted to view on paper rather than electronically).

It's just disappointing to have to put in all this extra code! If they could just support the same properties and features ... grr ...

By the way, specifying a width in cm (in a style, because you can't do it in the width property of a table) works fine in Firefox 3, and it seems to work in Chrome as well, although without a print preview function, I can't tell for sure (on my screen, the text in Chrome appears to be as wide as the text in Firefox).


Sep 19, 2008 at 11:29 AM // reply »
3 Comments

print to pdf to get around the print preview omission.


Post Comment  |  Ask Ben

Recent Blog Comments
Nov 21, 2009 at 6:47 PM
Hal Helms - Real World Object Oriented Development, Sarasota - Day Five
@charlie griefer, Thank you.. ... read »
Nov 21, 2009 at 5:15 PM
Using ColdFusion Structures To Remove Duplicate List Values
@Jose Galdamez, Oh heh yeah I didn't paste the whole code. I should have defined the vars -- my bad. It's fixed thou. Thanks. ... read »
Nov 21, 2009 at 4:49 PM
Styling The ColdFusion 8 WriteToBrowser CFImage Output
Great work yet again Ben! Whilst I didn't use this whole code, I copied some of your regex code for a similar problem with the lack of an alt attribute and unescaped ampersands in CFIMAGE for Railo 3 ... read »
Nov 21, 2009 at 1:13 PM
My First ColdFusion Builder Extension - Encrypting And Decrypting CFM / CFC Files
@Ben, Because I am pedantic, I just want to make sure that everyone knows there is absolutely no encryption going on. There is only encoding and obfuscation. The cfencode tool only obfuscates your C ... read »
Nov 21, 2009 at 12:28 PM
Using ColdFusion Structures To Remove Duplicate List Values
@Jody I can't seem to get your code sample to work. If you are still having problems, try this code out and see if it gets you what you wanted. <!--- Comma delimited list with various duplicates ... read »
Nov 21, 2009 at 11:03 AM
Groovy Operator Overloading Does Not Work In The ColdFusion Context
Hi Ben, Thanks for this informative post. Now I am reading ur old posts too ... read »
Nov 21, 2009 at 10:56 AM
HostMySite.com Has The Best ColdFusion Hosting
@Mehul, Yes very nice people, however several downtimes per day which was not acceptable. Hence we had to move out. I am glad you are having good luck with them so far. ... read »