HTML Support for PDF Landing Pages
Margin Content (Headers & Footers)
You can put content into the page margins, for example to create headers, footers or page numbers, by specifying content for any of the following locations:
The top margin:
- top-left
- top-center
- top-right
The left margin:
- left-top
- left-middle
- left-bottom
The bottom margin:
- bottom-left
- bottom-center
- bottom-right
The right margin:
- right-top
- right-middle
- right-bottom
The four page corners:
- top-left-corner
- top-right-corner
- bottom-left-corner
- bottom-right-corner
You add this content by specifying a nested at-rule with one of the names listed above inside of the page rule of the page that you want to affect.
For simple content, you can specify the content right there in the rule.
@page { @top-center { content: "This goes into the top margin, centered."; } }
For more complex content, for example content that in turn uses more complex HTML formatting, or if you want to have different content on different pages, you can specify the content in an element on the page and specify a rule to put this element in the corresponding margin location (instead of appearing normally on the page). This is done in two steps:
In the at-rule, you specify the element that is supposed to appear in this margin location, using the element function with the element's identifier. (Can be any valid CSS identifier; the example below uses "my-identifier").
@page { @bottom-center { content: element(my-identifier); } }
Then put the element that is supposed to appear in this margin location into the document itself
(i.e. somewhere inside of the <body>
) and give it a
position:running() with the same identifier as used in the at-rule.
<div style="position:running(my-identifier)">This element goes into the bottom margin.</div>
Take care when choosing the position in the source code where you put this element, because the position of the element in the document determines which pages will use this element in their margin and which not: Only the page on which the element is located plus all later pages will use the element. Any previous pages will not use it.
Of course, additionally the page must also match the at-rule that references the element. Pages that do not match
the at-rule will not use the element at all, even if the element was located on or before the page in question.
For example, if you reference the element in a @page:left
rule that affects only "left" pages, then
even it you put the element on the very first page, it will not appear on this page, as the first page is, by
convention, a "right" page. It will also not appear on any later "right" (=odd numbered) pages.
Tip: To make sure that a margin element appears on every page, reference it from a default @page
rule
and put the element itself into the beginning of the document, right after the <body>
tag.
More precisely: The first element with a matching ID on the page is used as the margin element. If no such element is present on the page itself, then the previous pages are searched for elements with this ID. If any are found, then the last of these is used as the margin element for the page. If none are found, then the page does not get this margin element.
This allows you to redefine a margin element on a later page (and its following pages). There are some situations where this can be useful. For example, if the first few pages of the document shall have a different header/footer than the rest of the document.
Note, that when putting an element into the top or bottom margins, the element always behaves like a block level element that spans the whole width of the top or bottom. So, for such elements, the locations top-left, top-center and top-right (and the same for bottom) have effectively the same effect, as they all create a full width element. To get the desired left, center or right alignment, use the appropriate text-align styles on the element itself.
Page Numbers
Page numbers are probably one of the most common use of margin content. They can be added to any of the margin locations (as explained above) by specifying a simple content directly in the CSS rule, where you use the counter function.
You can use counter(page) for the current page number or counter(pages) for the total page count.
For example, the following rules add the current page number to the bottom corner of each page, on the left or right respectively:
@page:left { @bottom-left-corner { content: counter(page); } } @page:right { @bottom-right-corner { content: counter(page); } }
And this rule adds a more elaborate page information to the footer of each page, with the page numbers given in uppercase roman numerals:
@page { @bottom-center { content: "This is page " counter(page, upper-roman) " of " counter(pages, upper-roman); } }
Elaborate Page Numbering Example
With a bit of creative CSS and HTML code, you can manage some quite elaborate numbering schemes.
For example, imagine a document that consists of an intro part and a main part, where the intro part is supposed to get page numbers with lowercase roman numerals (i, ii, iii, iv, ...) and the main part is supposed to get normal decimal page numbers, but shall restart with page number 1.
To achieve this, we first define that every page shall have an element with the ID "page-number" in the bottom right corner.
@page { @bottom-right-corner { content: element(page-number); } }
Then we prepare CSS classes both for lowercase roman numbering and normal decimal numbering.
Both classes get the position:running
style with our "page-number" ID that matches the
element for the bottom right corner (see above). Since both classes use the same ID, a later element
will replace a previous element, so the decimal numbering on later pages can replace the roman numbering
on previous pages.
.page-number-roman, .page-number-decimal { position: running(page-number); }
And for each class we define the content to be the counter in the desired style. For this we have to
use the ::before
pseudo element to be able to set the content
.
.page-number-roman::before { content: counter(page, lower-roman); } .page-number-decimal::before { content: counter(page); }
Finally, we define a helper class that creates a page break and restarts the page numbering. We will use this to demarcate the switch from the intro part with roman numbering to the main part with decimal numbering.
.break-and-restart-page-numbers { page-break-before: always; -fs-page-sequence: start; }
We now use these classes in the following way:
At the very beginning of the document, right after the <body>
tag, we put this
element which, because of the @page
rule, will be used for the bottom right corner
and which, because of its CSS class, will there generate a roman numeral page number.
<span class="page-number-roman"></span>
And after the intro part, at the very beginning of the main part, we put this element, which causes a page break and restarts the page numbering, and also replaces the element that is put into the bottom right corner which one that generates decimal page numbers.
<div class="break-and-restart-page-numbers"> <span class="page-number-decimal"></span> </div>
So, as a whole, our sample looks like this:
<html> <head> <style> @page { @bottom-right-corner { content: element(page-number); } } .page-number-roman, .page-number-decimal { position: running(page-number); } .page-number-roman::before { content: counter(page, lower-roman); } .page-number-decimal::before { content: counter(page); } .break-and-restart-page-numbers { page-break-before: always; -fs-page-sequence: start; } </style> </head> <body> <span class="page-number-roman"></span> <!-- Intro part content goes here, spanning several pages that will be numbered with roman numerals. --> <div class="break-and-restart-page-numbers"> <span class="page-number-decimal"></span> </div> <!-- Main part content goes here, spanning several pages that will be numbered with decimal numerals, restarting at page 1. --> </body> </html>