I've designed an HTML report with several div
s and table
s. Now my client asks me to put a repeating header at the top of each printed page. This is not possible using plain CSS and HTML as far as I know. Just as a try, I put header div element inside a thead to which I applied display: table-header-group
in order to be displayed, and put all other elements of the report as rows of the main table but no success.
A workaround is to use @print { .header {position: fixed; top: 10px} }
in order
to repeat .header element at the top of each page. But for this work, we should put a blank space at the top of each new page; otherwise fixed header element is mixed with other elements at the top of table.
As another workaround I can compute elements height at render time and put manual page breaks where needed. So I want to know if there is any Javascript library available to execute at page load and computes all render-time heights of div elements of the page and put a zero-height div element with page-break-before: always;
before each div which exceeds height of an A4 paper. For suppose the following divs result in 14, 10, 8, 9, 6, 13, and 6 centimeter height at render time. I want the library put a page-break dummy dive element at specified locations:
<div id="d1">...</div>
<div id="d2">...</div>
<!-- here, because 14+10+8 exceeds 30cm -->
<div id="d3">...</div>
<div id="d4">...</div>
<div id="d5">...</div>
<!-- here, because 8+9+6+13 exceeds 30cm -->
<div id="d6">...</div>
<div id="d7">...</div>
Here is my final solution. The following code is executed at page load. My page was solely composed of a number of divs. Two divs as headers and the other divs (containing tabular data) as details. I assumed always printing in portrait scheme and also assumed A4 size (= ~21x30cm). I also assumed 4.5cm margins for left-right and top-bottom of the page. The code first resizes divs to a portrait compatible width (so that all tables are divs are resized automatically). Then I iterate over non-header div elements to add a page break when height exceeds A4 height. I also cloned and added header elements atop of each page through this code.
// page width in pixels
function pw() {
return cm2px(16.5);
}
// page height in pixels
function ph() {
return cm2px(25.5);
}
function px2cm(px) {
return px * 2.54 / 96;
}
function cm2px(cm) {
return cm * 96 / 2.54;
}
$(function() {
$('.section > div').each(function(){
$(this).width(pw() + 'px');
});
hh = $('.section > div.heading');
headingHeight = hh.eq(0).height() + hh.eq(1).height();
h1 = hh.eq(0).clone();
h2 = hh.eq(1).clone();
var h = headingHeight;
var pageHeight = ph();
$('.section > div').not('.heading').each(function(){
if (h + $(this).height() + 14 > pageHeight) {
h1.css('page-break-before', 'always');
$(this).before(h1.clone());
$(this).before(h2.clone());
h = $(this).height() + 14 + headingHeight;
} else {
h += $(this).height() + 14;
}
});
});