Stylesheet for printing
CSS can also be applied for styling paged media. Major browsers support basic primitives for print stylesheets. However, some more advanced features are only supported by proprietary render engines.
Loading the print stylesheet
A complete stylesheet document or single CSS rules can be contextually loaded based on the media type. There are basically 4 different media type contexts for stylesheets:
- all: which is default and is used for all contexts.
- screen: only for screens like desktops, mobile phones or tablets
- print: only for printers
- speech: the special context for screenreaders, which reads the page out loud
Link attribute
Inside the head tag of a HTML-document stylesheet links are declared. The media attribute can be specified to only load a stylesheet for the print
context.
<link rel="stylesheet" href="print.css" type="text/css" media="print">
@media rule
Within a stylesheet the @media
rule can be used to contextualize a single or several styling rules only.
@media print {
/* css rules */
}
Page breaks
A powerful feature for print stylesheets is the possibility to define when a page break should occur. Therefore the page-break-*
properties are available.
The rules page-break-before
and page-break-after
define if a page break should occure before or after a HTML element. The attribute values auto
, always
and avoid
are probably self explanatory. The values left
and right
are especifically available for two-sided documents. The left
value means that the next page should be a left page of a two-sided document. This might add a blank page if the next page is a right page. For a right
value it works the same, however the other way around.
page-break-before: auto|always|avoid|left|right;
page-break-after: auto|always|avoid|left|right;
Additionally, the rule page-break-inside
allows for avoiding page breaks inside an element.
page-break-inside: auto|avoid;
The special @Page rule
The @page
rule allows for specifing the format of a printed page. It is important to note, that only a couple of CSS properties can be changed inside @page
(others are ignored). The @page
rule allows specifying margin
, size
, page-break-*
.
@page {
/* css properties */
}
Furthermore it is possible to use the pseudo-classes :first
, :blank
, :left
, :right
to target pages more specifically.
Handling orphans and widows
Orphans and widows are very annoying effects when preparing a text for print. An orphan is the first line of a new paragraph, which is printed on the bottom of a page. A widow is the last line of a paragraph, which is printed on the top of a new page.
The orphans
and widows
rules allow for stating the minimum number of lines a pragraph needs to have either on the old or the new page. The page-break-inside
rule can be used to avoid page breaks inside paragraphs altogehter.
@media print {
p {
orphans: 3;
widows: 3;
}
}
Some Examples
Print the href of an a-tag
A webpage typically includes weblinks, which are very useful inside the browser, but provide no functionality on paper. However, it might be good practice to at least add the link target placed after the link text.
a[href^=http]:after {
content:" [" attr(href) "]";
}
The above snippet would print the URL in square brackets after a link text, which has a weblink inside the href attribute.
Chapter numbers
CSS has support for counters, which are a handy feature for numbering chapters. Everytime a CSS rule is applied inside a document a counter can be changed: counter-increment
for incrementing the counter or counter-reset
for resetting the counter to 0. The value of a counter can be accessed with the function counter(countername)
and the respective counter name. Counters can have any name like a variable in programming.
h1:before {
counter-increment: header1;
content: counter(header1) ". ";
}
h1 {
counter-reset: header2;
}
h2:before {
counter-increment: header2;
content: counter(header1) "." counter(header2) ". ";
}
h2 {
counter-reset: header3;
}
h3:before {
counter-increment: header3;
content: counter(header1) "." counter(header2) "." counter(header3) ". ";
}
The above snippet would place a chapter number like 1.3.2
. before a HTML heading (h1, h2, h3).
Page numbers
Printing page numbers e.g. inside a footer is possible with CSS counters as well. Unfortunately, the presented solution works only in Firefox for now. The Chrome Browser doesn’t increment the counter as the footer is placed with position fixed
.
<footer>
<div id="page-number"></div>
</footer>
@media print {
footer {
position: fixed;
bottom: 0pt;
left: 0pt;
right: 0pt;
text-align: center;
}
#page-number::after {
counter-increment: page;
content:"Page " counter(page)
}
}
Testing
A general workflow for developing and testing print stylesheets would look something like this:
- Modify the print stylesheet
- Reload the stylesheet inside the browser
- Open the menu and select
print
and check theprint preview
This is quite cumbersome to always require to navigate to print preview. Fortunately, Chrome supports emulation of the print
media type. The instructions can be found here. This offers some simplification for developing print stylesheets. However, elements like headers, footers and page-breaks cannot be tested with this approach and require opening the print preview.
PDF generation
There are many software libraries for generating PDFs. To name just a few:
- FPDF: FPDF is a PHP library for generating PDFs.
- PDFBox: PDFBox is Java library for generating PDFs.
- PDFKit: PDFKit is JavaScript library for generating PDFs.
Many of these libraries use their own API and/or templating engines for PDF generation. For developers it is quite a tedious task to learn these. Since e.g. the Chrome browser supports a headless mode, one can use it for PDF generation.
With the following command one can generate a PDF from a website (styled with a printable stylesheet). $LOCATION
is the local filepath where the PDF should be stored. $URL
is the URL of the website to print. Of course the command chrome
has to be available via command line (check PATH
environment variable).
chrome --headless --disable-gpu --print-to-pdf=$LOCATION $URL
Using a headless browser for PDF generation has the advantage that no new library and template language has to be learned by a developer.
Conclusion
Browsers generally support print stylesheets. Unfortunately, major browsers don’t support some key CSS functionality for paged media. There are several working drafts from the W3C like CSS Paged Media Module Level 3 and CSS Generated Content for Paged Media Module, but currently no major browser has support. For advanced paged media support there is a proprietary and quite pricey render engine called prince, which has support for the W3C drafts.