layout | title | short | lead | author | date | tags | coverImage | coverImageCredits | ||
---|---|---|---|---|---|---|---|---|---|---|
layouts/content.njk |
Generating CSS for print |
Generating CSS for print |
TEI Publisher 8 will support creating print output using CSS Paged Media. This supplements the existing FO and LaTeX output modes. |
Wolfgang Meier |
2023-02-12 |
|
bank-phrom-Tzm3Oyu_6sk-unsplash.jpg |
TEI Publisher 8 will support creating print output using CSS Paged Media. This feature supplements the existing FO and LaTeX output modes. While FO and LaTeX require quite some customization in the ODD, Print CSS extends the existing HTML view and CSS styles to layout the text on the printed page.
Though it has improved, browser support for CSS Paged Media (often also called Print CSS) is still insufficient. However, there are tools to fill the gap. The starting point for my recent exploration into this technology was an edition of medieval hagiography. The editors requested a printout, which should ideally resemble the future website as closely as possible, so corrections could be done on paper. While LaTeX does provide all the fancy features needed (e.g. an aligned parallel layout of transcription and translation using the powerful reledpar package), the result would quickly diverge from the web version, hence would not be suitable for the review process.
Looking into CSS Paged Media as an alternative, I was surprised by what is possible by now in the browser. The book had quite a complex layout, using different types of marginal notes, text critical apparatus etc. Even though I could not realize every feature just within the browser and had to switch to an external utility (see below), the results were satisfactory and would certainly be sufficient for a slightly simpler edition.
Page from the TP demo with margin notes and running head rendered with paged.jsWe have therefore decided to integrate this approach more tightly into TEI Publisher, providing a separate print preview page for those sample documents for which it makes sense, as well as an API endpoint to retrieve the complete HTML of a document targeted at print.
The new feature will become available with the TEI Publisher 8 release. If you would like to experiment with it right now, feel free to use one of the docker images - which always reflect the current state of development - or build TEI Publisher yourself.
The new print preview page includes a brilliant javascript library, paged.js, which fills many of the gaps in browsers concerning CSS Print support. Without this library, web browsers would ignore most parts of the page layout and just generate a very basic printout. With paged.js though, you can use the browser's default print dialog to get a pretty fancy printed version.
paged.js is open source and still under development, so there are limitations (see below). For linear documents like the TEI Publisher documentation it does produce very good results though.
Obviously not everything you can do on a screen will work on paper. For example, the alternate
behaviour defined in the TEI guidelines will by default generate a popup if you use the web
output mode in TEI Publisher. We can't do that on paper. Therefore we need a way to distinguish between HTML targeted at the screen and HTML for print by using a different output mode in the ODD. This requires a change in the underlying core library of TEI Publisher, called tei-publisher-lib
.
The newly released tei-publisher-lib
version 3.0.0 reassigns the print
output mode to generate HTML for print. print
extends web
, overwriting the two behaviours, which would fail on paper: note
and alternate
. Both involve popups. print
just outputs them as plain HTML to be processed by print CSS styles.
You'll need to update tei-publisher-lib
to benefit from the newly added features. print
was previously defined as a synonym for fo
and generated XML output to be further processed by an XSL/FO engine like Apache fop. Reassigning it constitutes a breaking change (hence the major 3.0.0 version, which indicates: not backwards compatible), though the fo
mode will still work as before. Please keep this in mind when you decide to upgrade and read the instructions.
TEI Publisher 8 will include a default CSS stylesheet for print, residing in resources/css/print.css
. The API endpoint, which generates HTML for print, automatically injects this. The default stylesheet sets the paper size to 'A4', adds margins for recto and verso pages, page numbers in the respective bottom corners, and most important: a footnote area at the bottom. HTML elements with class footnote will be output there.
You can extend this by adding your own print styles as follows: if you have not done that yet, create an empty CSS file next to the location in which your ODD is stored (odd
in TEI Publisher or resources/odd
in a generated app). Associate this with your ODD by adding a corresponding <rendition>
element to the <teiHeader>
:
<encodingDesc>
<tagsDecl>
<rendition source="shakespeare.css"/>
</tagsDecl>
</encodingDesc>
Note that you need to recompile your ODD whenever you change the associated CSS. This is needed as TEI Publisher combines the stylesheet with any <outputRendition>
styles defined in the ODD.
All CSS rules targeted at print should go into a @media print
section. To start with, we could add a running head to the left and right pages:
@media print {
@page:left {
margin-left: 1cm;
margin-right: 1cm;
@top-left {
content: string(runningHead);
font-family: var(--pb-heading-font-family);
}
@bottom-left-corner {
content: counter(page);
font-family: var(--pb-heading-font-family);
}
}
@page:right {
margin-left: 1cm;
margin-right: 1cm;
@top-right {
content: string(runningHead);
font-family: var(--pb-heading-font-family);
}
@bottom-right-corner {
content: counter(page);
font-family: var(--pb-heading-font-family);
}
}
}
Key here are the added @top-left
and @top-right
sections, which take their content from a - so called - named string, in this case: runningHead
. We'll set this named string using the content of each <h1>
heading output by our ODD transformation:
@media print {
...
h1 {
string-set: runningHead content(text);
break-before: page;
}
}
We also request that a page break is inserted before every title. As you have full control over the ODD which generates the HTML, you could also decide to use a different element or a given class name. You can even combine multiple named strings into one running head (as demonstrated by the TEI Publisher documentation).
The chapter on generated content and margin boxes in the paged.js documentation explains the concepts very well, so please refer there for further information.
Another feature working nicely with the paged.js library behind TEI Publisher's print preview page is a multi-column layout. To enable two columns, simply add columns: 2
to the enclosing parent element. You can also specify that headings should span across both columns as shown before:
@media print {
...
section {
columns: 2;
}
h1, h2, h3 {
column-span: all;
text-align: center;
}
}
The paged.js library is still under development and has its limitations. For example, I have not been able to create a two column layout with aligned transcription and translation, though I tried various approaches. Using a table worked as long as both parallel paragraphs would fit on the page, but longer paragraphs were separated.
Fortunately there are several tools which run outside the browser and provide better coverage for Print CSS, though the majority of them is commercial. A list can be found on print-css.rocks.
ToolbarMost of those tools operate on the command line and expect an HTML file as input. To simplify this task we created an API endpoint in TEI Publisher, which retrieves the print optimized HTML for an entire document and injects the necessary stylesheets. You can copy the endpoint URL for a given document by using the corresponding button in the print preview interface.
For example, using Prince XML on windows, one can paste this URL directly into the application's dialog. The endpoint URL has the following structure:
/api/document/test%2Forlik_to_serafin.xml/print?odd=serafin.odd &base=%2Fexist%2Fapps%2Ftei-publisher%2Ftest%2F &style=resources%2Ffonts%2Ffont.css &style=resources%2Fcss%2Fprint.css
Here odd
defines the ODD to use for the transformation, base
is the base URI from which additional stylesheets or images are loaded, and style
lists one or more additional CSS stylesheets.
While I have many years of experience with FO and worked on some LaTeX-based projects, I did not really look into Paged Media CSS until recently. Though browser support is still lacking, a library like paged.js definitely fills the gap, at least for documents not requiring parallel layout or huge tables (see the TEI Publisher documentation for example). For complex layouts, commercial software like Antennahouse or PrinceXML (to just name two) can provide high quality print.
Two pages from the TEI Publisher documentation rendered with paged.jsThe one great advantage of using Print CSS instead of FO or LaTeX is that you can work on the web and the print version at the same time and generate both from the same ODD, distinguishing the output mode in a few places only. This allows for rapid prototyping and quick review cycles.
We'd like to ask the community to support us in this area by contributing further examples. Help us push the limits of what can be done.