Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at cf.Objective() 2011 (Minneapolis, MN) with:

Ask Ben: Optimizing Tables For Printing

By Ben Nadel on

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:

  • <!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.

Tweet This Great article by @BenNadel - Ask Ben: Optimizing Tables For Printing Thanks my man — you rock the party that rocks the body!

Looking For A New Job?

100% of job board revenue is donated to Kiva. Loans that change livesFind out more »

Reader 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.

Reply to this Comment

@Todd,

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

Reply to this Comment

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.

Reply to this Comment

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.

Reply to this Comment

@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?

Reply to this Comment

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 ...

Reply to this Comment

@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!!!

Reply to this Comment

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 :(

Reply to this Comment

@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. :)

Reply to this Comment

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.

Reply to this Comment

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>

Reply to this Comment

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. :)

Reply to this Comment

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.

Reply to this Comment

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.

Reply to this Comment

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.

Reply to this Comment

@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.

Reply to this Comment

@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).

Reply to this Comment

@Mallik (or Ben),

Did you ever get/figure out an answer to this question of selective display of header/footer?

For a job at work, using CF 8.01 (all patches applied, as far as I know,) we are hoping that there is a way to manipulate the "cfdocumentitem" tag logic such as to selectively control which pages a header (or footer) actually appears on.

For example, we want to not display the header on the first page, but to go ahead and display it on every page thereafter.

Our main issue so far is that when trying to reference the "cfdocument.currentpagenumber" inside the "cfdocumentitem" tag, CF complains that the variable doesn't exist. (A problem I have seen other have experienced: http://blog.dkferguson.com/index.cfm/2008/1/11/CFDocument--pdf-generation-broke-after-CF8-upgrade )

"Any advice you could give me that might point me the way of success would be, by me, appreciated." - Ainsley Hayes, The West Wing

"Well, not speaking in iambic pentameter might be a step in the right direction." - Lionel Tribbey, The West Wing

Thanks all,

David L.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.