I'm developing a tool which allows generating PDFs from HTML templates using FlyingSaucer's OpenPDF library, which supports CSS 2.1.
The PDFs being generated need to have a header at the top of each page. That header includes user-provided content, so the height varies.
However, we want a reduced header that displays fewer fields on subsequent pages.
Initially, I was putting the header into a <thead>
element and forcing it onto each page with -fs-table-paginate: paginate
in the CSS.
However, to support showing a reduced header on subsequent pages, I switched to the following CSS:
display: block;
text-align: center;
font-size: 50pt;
position: running(first-page-header);
}
div.header {
display: block;
text-align: center;
position: running(header);
}
div.footer {
display: block;
text-align: center;
position: running(footer);
}
@page :first {
@top-center {
content: element(first-page-header)
}
@bottom-center {
content: element(footer)
}
}
That allows the header to include different content on subsequent pages, but the height of the header and footer are fixed to a certain number of pixels. I can adjust that by setting a margin
attribute on the pages, but I either leave a bunch of empty space or I risk the header text overlapping with the body text.
I know it's possible to inject page numbers using CSS, which seems like it might possibly lend itself to rendering different content in the header depending on the page number, but I suspect that's not going to be a good solution.
Possibly there's some trick with :first-child
that would allow rendering the first page's header differently?
If it helps, these are actually not just HTML, but Thymeleaf templates; that's how I'm injecting the user-provided content. However, since the conversion to a PDF with pages is after the Thymeleaf step, it doesn't seem likely to help.
I don't think rendering to PDF, measuring the height of the header, and then setting the top margin accordingly on a second render is a particularly good strategy.