Running headers and footers are found in most books. They are there to remind readers of what they are reading, and to navigate within the book. This guide will show you how to create running headers and footers from your HTML documents.
The formatter of choice is Prince, an HTML-and-CSS-to-PDF converter. The screenshots you see, and the PDF documents linked from this guide, have all been generated with Prince. You can easily create the same pdf files by downloading Prince and pointing it to the HTML links provided in this document.
In the most basic example, a string is placed at the top right of every page in the document:
html@page { @top-right { content: "Chapter 1: The Machine" }}
Inserting a string into the style sheet is easy, but the style sheet is then tied to a specific document. A more reusable style sheet will pick up the string from the document itself.
In the following example, the content of the h2
element is copied into a named string called title
. The named string is then, in the second line, referred to inside the string()
function:
htmlh2 { string-set: title contents } @page { @top-right { content: string(title) }}
When more chapters are added, the running page header is automatically updated:
htmlh2 { string-set: title contents break-before: page; } @page { @top-right { content: string(title) }}
Page numbers are often placed at the bottom of the page:
html@page { @bottom-right { content: counter(page) }}
The predefinded counter called page
is automatically increased at every page turn. Another counter, called pages
holds the total number of pages in the document.
html@page { @bottom-center { content: counter(page) " of " counter(pages) }}
In the previous example, notice how the two counters are combined with a litera string between them.
In the examples above, the chapter number has been written into the HTML code. It's often better to use CSS counters to generate these:
html@page { @top-right { content: "Chapter " counter(chapter) ": " string(title); } } h2 { counter-increment: chapter; string-set: title contents; break-before: page; } h2::before { content: "Chapter " counter(chapter) ": "; }
On the first page of a chapter, where the chapter title is shown, you probably do not want to show a running header.
htmlh2 { string-set: title contents; prince-page-group: start; /* enables :first, see below */ break-before: page; } @page { @top-right { content: string(title) }} @page :first { @top-right { content: none }}
In the above example, the first @page-rule sets a running header on the top right of every page. However, the last @page-rule overrides the first on pages that are considered to be first
. Normally, only the first page of a document is considered to be the first
. However, by setting prince-page-group
on the chapter heading, pages with chapter headings are also considered to be first
.
You can use the CSS properties you know & love on running headers:
html@page { @top-right { content: string(title); font-style: italic; vertical-align: top; padding-top: 1em; } }
You can also copy elements into the running headers, not just strings. Here is an example where a mathematical equation is added to the running header:
html@page{ @top-right { content: element(header); } } div.math { position: running(header); text-align: right; } ... <div class=math> The solution is: <math><msqrt><mi>x</mi></msqrt></math> </div>
Notice that the text-align
property is set on the h3
element; when using running elements, properties are typically set on the element itself, and not inside @page
.