While perusing a discussion board, I read a
question from a concerned developer who was trying to
programmatically create headers and footers and insert page breaks
on an HTML page. This is next to impossible considering what your
output is, since there’s no easy way to figure out the browser’s
current settings for margins, page sizes, etc. However, if you want
to force widths and page breaks, you can do it.

One way to accomplish this is to use TABLEs. In
this article, I’ll show you how to create the headers and footers
necessary to dynamically insert these items to create a formatted
hardcopy. (Note: I used IE 6.0 to test the code in this tip. It
also works on 5.0 and above, because I use the @media pseudo-class
available for the STYLE element in IE since 5.0.)

The easiest way to create this functionality is
to use TABLEs. However, your formatted output must contain
individual rows that don’t exceed the printed page’s height. Also,
your TABLE must not exceed the width of the printed page. Since you
don’t have any control over landscape or portrait, you must make
some assumptions. You’ll assume that the orientation of the
document is portrait with 1″ margins left and right, 0.25″ margins
top and bottom, and the paper size is 8.5″ X 11″. This means that
you have 6.5″ total width for output, so your TABLE width will be
set to 6.5in, no border. At the top of the table, you’re
going to create two hidden DIVs that will serve as the header and
footer. The DIVs have set widths and heights, and the overflow
style attribute is set to hidden. This sets the foundation
for your output. In order to create the page breaks, headers, and
footers, you’ll have to incorporate some JavaScript after the page
loads.

The idea for creating the formatted output is
to copy the header and footer DIVS into hidden rows. However,
you’ll set the display style attribute to inline for @media
print. Also, you’ll set the page-break-after style attribute to
always for the TR just before the footer.

During the BODY onload event, iterate through
all the rows to determine whether the row offsetTop plus the
offsetHeight exceeds the available length of the page. The
available length is the length of the page minus the sum of the
heights of the header, footer, and top and bottom margins. So, if
the header height and footer heights are each 1″, the top and
bottom margins are 0.25″, and the page length is 11″, then the
available width is 8.5″: 11 – (1 x 2) – (0.25 x 2) = 8.5.

Listing A contains the HTML that accomplishes this
task. When you examine the sample code, you’ll notice
that the header and footer are two hidden DIVs that appear right
before the TABLE element. The TABLE tbl1 contains multiple TRs.
Each of the rows is identified as t1 to help iterate through them
using the all collection. This example will only work with
two or more rows. I create the style class hdrftr to
identify when those items should be displayed. The JavaScript
details how the functionality is created.

First, a header row is added to the top of the
table. Next, each row is examined to determine if the top
coordinate plus the row height plus the footer height — 1in *
screen.deviceYDPI or just screen.deviceYDPI — meets or exceeds the
total available height. If this value matches the available height,
the current row is set to have a page break after it. If this value
exceeds the available height, the previous row is set. The row of
interest is then used to append a footer row after it and a header
row is added after the footer row. This process continues until all
rows are examined. Finally, a footer row is appended to the end of
the table. The footer row contains absolute positioning to avoid
inadvertent page-breaks from the browser, thus giving us a little
margin of error. Also, each subsequent page must make a provision
for the additional header rows that we add: (page – 1) * 1, where
(page – 1) is the subsequent page number and 1 is the height of the
header.

Keep your developer skills sharp by automatically signing up for TechRepublic’s free Web Development Zone newsletter, delivered each Tuesday.