Prince
  • Buy Prince
  • Samples
  • Documentation
  • Forum
  • Download
  • Installation Guide
  • User Guide
  • Reference Guide

Styling

When preparing a document with HTML and CSS, you need to first create the content - but then you need to style it to make it visually appealing. You can choose which fonts to use, how to format your text and your paragraphs, choose the layout for your page, give your text, background and style some color, insert images - and much more!

In the following sections you can find detailed information on how to achieve this with Prince.

The major difference between formatting for the web and PDF/Print is that PDF is paginated, which means that content is placed on discrete pages, as opposed to one continuous flow, typical for web pages.

Prince allows you to control a number of options that affect how PDF formats pages, from straight-forward options such as page size, to decorations, headers and footers, numbering and page breaking options. See detailed information in the Paged Media section.

Prince applies default styles to all (X)HTML documents - these style rules can be found in the html.css style sheet, located in the style folder inside the installation directory (see Installation Layout).

Fonts

Prince supports WOFF (Web Open Font Format), TrueType and OpenType (TTF and CFF) font formats.

Defining a font family

To define the font, or the fonts to be used in a document, the font-family property is used. Prince will try to use the specified font, and should glyphs be missing, it will silently fall back to the next font in the cascade - typically a generic font family.

To prevent this font switching mechanism and force Prince to only use the defined font, the special keyword prince-no-fallback is available: it triggers a warning if any glyphs are not found in the specified font, instead of switching to another one.

h1 { font-family: MyFont, prince-no-fallback; }

The @font-face at-rule can be used to define custom font names. The font-family descriptor defines the font family name that will be used in all CSS font family name matching, and the src descriptor specifies the resource containing font data. They both are required for the @font-face rule to be valid.

The src descriptor can define the resource with a url() function - an optional format() function defines the format of the remotely fetched font. Alternatively, the local() and prince-lookup() functions can be used - the former searches for locally installed system fonts, while the latter will also find fonts defined by other @font-face rules. See CSS Functional Expressions.

@font-face {
  font-family: MyFont;
  src: prince-lookup("MyFont"),
       url("http://example.com/MyFont.ttf") format("truetype");
}

In this example we are defining a new font face, called MyFont. We instruct Prince to check if the MyFont truetype font is installed locally or already defined by another @font-face rule, and, all failing, to download it from a remote location.

When a chosen bold and/or italic font is missing, Prince tries to artificially synthesize the missing font - i.e. to embolden or italicize the original font. However, it might lead to undesired results. This feature can be disabled with the --no-artificial-fonts command-line option.

OpenType Features in Prince

Prince supports OpenType features, and enables certain ones by default in specific scripts. The following ones are enabled by default in Prince:

Script Enabled features
Latin, Greek, Cyrillic ccmp, liga, dist, kern*, mark, mkmk, vrt2/vert
Arabic/Syriac ccmp, rlig, calt, liga, mset, isol, medi, fina, kern, curs, mark, mkmk
Indic ccmp, and many other Indic-specific substitutions
Other scripts kern*, mark, mkmk

* Kerning can be disabled with the keyword prince-no-kerning of the font-variant property.

Microsoft has a list of the OpenType feature names here.

It is possible to enable other OpenType features by using the font-variant CSS property with the prince-opentype() function (see CSS Functional Expressions).

Care must be taken in which order the features are enabled! And please note that enabling one feature will disable all the default features.

Generic font families

Prince maps the CSS generic font families to the Microsoft Core Fonts. The Microsoft Core Fonts are pre-installed on Windows and MacOS X systems but not on Linux systems. To use them on Linux you must install the msttcorefonts package, which is available for most Linux distributions.

The following table shows the default fonts for the main languages on Windows, MacOS X and Linux.

Generic family Operating system Language Actual font
serif Windows Latin Times New Roman
Chinese MingLiU
Japanese MS Mincho
Korean Batang
Devanagari / Hindi Mangal
MacOS X Latin Times New Roman
Chinese LiSong Pro
Japanese Hiragino Mincho ProN
Korean AppleMyungjo
Devanagari / Hindi Devanagari MT
Linux Latin Times New Roman, DejaVu Serif, DejaVu LGC Serif, Liberation Serif
Chinese AR PL UMing CN, AR PL SungtiL GB
Japanese Kochi Mincho, IPAMincho
Korean UnBatang, Baekmuk Batang
Devanagari / Hindi Lohit Devanagari
sans-serif Windows Latin Arial
Chinese
Japanese MS Gothic
Korean Dotum
MacOS X Latin Arial
Chinese LiHei Pro
Japanese Hiragino Kaku Gothic ProN
Korean Apple SD Gothic Neo, Apple Gothic
Linux Latin Arial, DejaVu Sans, DejaVu LGC Sans, Liberation Sans
Chinese AR PL UKai CN, AR PL KaitiM GB
Japanese Kochi Gothic, IPAGothic
Korean UnDotum, Baekmuk Gulim
monospace Windows Courier New
MacOS X
Linux Courier New, DejaVu Sans Mono, DejaVu LGC Sans Mono, Liberation Mono

The complete list of defaults, including details like e.g. the exact Unicode ranges Prince is using, can be found in the fonts.css file located in the installation directory of Prince resources. (See Installation Layout).

In order to redefine these defaults, see Redefining the generic font families.

Redefining the generic font families

The CSS generic font families can be redefined to use different fonts by editing the fonts.css file in the Prince installation (see Installation Layout). Each font family is defined using a @font-face rule, which maps a font family to an actual font either by name or by filename. (See Generic font families).

Here is an example of mapping the generic "sans-serif" font family to the local system font called "Trebuchet MS".

fonts.css

@font-face {
    font-family: sans-serif;
    src: local("Trebuchet MS")
}

It is also possible to map the generic font families to local fonts specified by the filename of the TrueType font file. This will usually require using multiple @font-face rules, one for each TrueType font file in the font family, which usually includes four files (normal, bold, italic and bold-italic). Here is an example of mapping the generic "sans-serif" font family to the "Trebuchet MS" font using filenames, assuming that the font is installed in the usual system directory on Linux.

fonts.css

@font-face {
    font-family: sans-serif;
    font-style: normal;
    font-weight: normal;
    src: url("/usr/share/fonts/truetype/msttcorefonts/trebuc.ttf")
}

@font-face {
    font-family: sans-serif;
    font-style: normal;
    font-weight: bold;
    src: url("/usr/share/fonts/truetype/msttcorefonts/trebucbd.ttf")
}

@font-face {
    font-family: sans-serif;
    font-style: italic;
    font-weight: normal;
    src: url("/usr/share/fonts/truetype/msttcorefonts/trebucit.ttf")
}

@font-face {
    font-family: sans-serif;
    font-style: italic;
    font-weight: bold;
    src: url("/usr/share/fonts/truetype/msttcorefonts/trebucbi.ttf")
}

Prince can be instructed not to use system fonts with the --no-system-fonts command-line option. Only fonts defined with @font-face rules in CSS will be available.

Layout

Layout is the way in which text and pictures are set out on a page. It defines the final look of a document. Prince understands layout by means of CSS, cascading style sheets.

In the following chapters we shall go through the main points when preparing the layout of a page. It mainly follows the general steps of layout for web pages: starting from Text formatting and Paragraph formatting, via the Box Model, until Tables, Lists, Columns, Floats, Flex Layout, and Footnotes.

A separate chapter, Paged Media, will analyze in-depth the major difference between formatting for the web and PDF/Print, namely that PDF is paginated, content is placed on discrete pages.

Text formatting

Text can be styled with CSS by defining font styles or text layout styles.

After choosing an appropriate typeface for your text with the font-family property (see Fonts), you can assign it different sizes with the font-size property.

Next up you should decide whether to give it some color. The default text color for a page is defined in the body selector, but each selector can have its own color.

body {
    font-family: Helvetica, Arial, sans-serif;
    color: blue;
}

Special formatting can be achieved through the font-style, font-weight, text-transform or text-decoration properties. All of these properties can also be set with the shorthand property font.

It is also possible to style the vertical alignment of text in an inline box with the vertical-align property. The value baseline is the default, sub and super align the baseline of the element with the subscript-baseline or superscript-baseline of its parent respectively. The text-top and text-bottom values align the top of the element with the top or bottom of the parent's font, while middle aligns the middle of the element with the baseline plus half the x-height of the parent.

In order to determine how compact the text should be displayed, the letter-spacing can be used. Alternatively, the property font-stretch might be used, but note that it does not change the geometry of any arbitrary font by stretching or shrinking it - instead, it merely instructs Prince to choose the most appropriate face of the font, if the selected font offers several ones. Also note that this property is not supported for system fonts on Windows.

In a similar fashion, the property word-spacing can be used to determine the distance between words.

The directionality of the text is controlled through the Writing Mode.

Paragraph formatting

Now that you have decided on the basic properties of the text, you can turn your attention to styling the paragraphs. The text-align property is used to control how text is aligned within its containing box, while the text-indent property determines the indentation of the first line of text in the element.

If the text-align property has a value of left, right or center, the text will be aligned to the left, right or center respectively. The justify value instructs Prince to justify text. It is not uncommon, in printed texts, to align text based on whether the text appears on a left or right page. To support this, two new keywords are added to the text-align property: inside is the same as 'left' on right pages and 'right' on left pages, and outside is the same as 'right' on left pages and 'left' on right pages.

Prince adds the property prince-text-justify to define how to treat justified text for CJK languages. The value prince-cjk allows space to be inserted between CJK characters when justifying even if there aren't any space characters.

The last line of an element can receive its own alignment style with the text-align-last property. It takes the same values as text-align.

p {
    text-align: justify;
    text-indent: 5em;
}

It is also possible to style the first line of a paragraph in a different way - to achieve this, the selector ::first-line is used.

p::first-line {
    text-indent: 8em;
}

It is not unusual to give the first letter of a paragraph a bigger font size than the rest of the paragraph. The selector ::first-letter is useful for this purpose.

p::first-letter {
    font-size: 2em;
}

One of the most common use cases is for so-called drop caps - large capital letters at the beginning of a chapter that have the depth of several lines of text.

In the following example we are selecting the first letter of the first paragraph, which gets styled much bigger than the normal text, and gets floated to the left. The normal text is wrapping around this first large letter.

p:first-child::first-letter {
    font-size: 5em;
    line-height: 3rem;
    float: left;
}

Another important aspect when formatting a paragraph is how compact the text lines should appear on the printed page. The property line-height can be used to determine the height of text lines.

The property line-stacking-strategy allows to choose whether individual lines should have their height determined based on their content, or whether all lines in a paragraph should have the same height, or a compromise where their heights are determined by their content and then rounded up to a multiple of the paragraph line height.

In order to lay out text in a well-balanced way, it might at times be necessary to hyphenate some words - to enable hyphenation, the hyphens property is used. For details please refer to the section on Hyphenation.

Prince also allows for line-breaking in certain situations even in the absence of whitespace - for example, after slashes in long URLs. This behavior can be disabled with the prince-linebreak-magic property for situations in which more precise control over line-breaking is preferred.

The property overflow-wrap controls wrapping behavior of last resort: whether it is better for a word to overflow its container, or to be broken at an arbitrary point (subject to white-space, and not splitting within a grapheme cluster), without adding a hyphen.

Prince does not support the value break-word of the property word-break to achieve a similar effect. Use the value break-all of word-break, or the property overflow-wrap with the value break-word instead.

Writing Mode

A writing mode describes the directionality of a script, i.e. it describes the direction the script is to be read. In (X)HTML, the language of a document is defined by the lang or xml:lang attributes. To control the rendering of the text, a couple of CSS properties can be used: the direction property defines the inline direction of the script, that is left-to-right (like e.g. Latin or Indic scripts) or right-to-left (like e.g. Arabic and Hebrew scripts).

The writing-mode property, on the other hand, describes the block direction of the script, namely whether the text should be laid out horizontally, top-to-bottom (like e.g. Latin or Arabic scripts), or vertically, right-to-left (like e.g. Chinese scripts). The default value is horizontal-tb, which means horizontal, top-to-bottom.

Prince sets the PDF direction based on the direction and writing mode of the document root element to support right-to-left books.

Changing the writing mode of a document, that is, the inline or block direction, not only changes the direction of the script, but also affects several other aspects of the printed document.

The page selector pseudo-classes :recto and :verso (see Selecting pages) are relative to the direction of the script. In a left-to-right script, :recto is the right-hand side of a spread, and :verso is the left-hand side, while in a right-to-left script these values are inverted: :recto defines the left-hand side of a spread, and :verso defines the right-hand side. See also Selecting pages.

Columns change their orientation when the writing mode is changed - writing-mode vertical-rl arranges the columns horizontally, top-to-bottom.

This can be used to rotate content - see Printing wide content sideways and Rotating content in table cells.

Box Model

All HTML elements follow the CSS box model. Their margin, border, padding and background can all be styled.

Margin

At the very outside of the box are the margins. Each margin's size can be set individualy with the properties margin-top, margin-bottom, margin-left and margin-right, or you can use the shorthand property margin to specify all four margins together. The syntax of the shorthand property is:

margin: top right bottom left

If there are only:

  • three values: then the left margin is set equal to the right margin;
  • two values: then the left margin is set equal to the right margin, and the bottom margin is set equal to the top margin;
  • one value: then all margins are made equal.

Prince expands the margin properties with margin-inside and margin-outside, defining the margin respectively on the inside or outside of a spread: inside is on the right when used on a left-facing page, and on left on a right-facing page; outside is on the left when used on a left-facing page, and on the right on a right-facing page.

Always keep in mind that margin-top and margin-bottom of blocks are combined (i.e. "collapsed") into a single margin according to a possibly rather complex behavior known as margin collapsing. The notable exception is the behavior of margins in Flex Layout.

Border

The border of a box can be styled with several border properties. The borders can either be individually styled with border-top, border-right, border-bottom and border-left, or the shorthand property border can be used to style all four borders of the box in the same way.

To style the borders, the border-color, border-style and border-width properties can be used. For each of them, also top, right, bottom and left variants are available to style each border separately.

The property border-radius property can be used for styling rounded corners.

The border-clip property splits the borders into parts along the border edge - the first part is visible, the second one is invisible, the third part is visible, etc.

Padding

The property padding defines the padding inside the box model. Each padding's size can be set individually with the properties padding-top, padding-bottom, padding-left and padding-right, or you can use the shorthand property padding to specify all four paddings together. The syntax of the shorthand property is:

padding: top right bottom left

If there are only:

  • three values: then the left padding is set equal to the right padding;
  • two values: then the left padding is set equal to the right padding, and the bottom padding is set equal to the top padding;
  • one value: then all paddings are made equal.

Background

The background of an element can be styled with the background-color and the background-image properties, or with the shorthand property background. See also Background Images.

Various standard properties are available to position the background, to clip it or to determine whether, and how it should be repeated. Prince extends control on the background with the prince-background-image-resolution property, used to control image size in print (see Image Size).

Display

Every HTML element is displayed in a way depending on what type of element it is. Most elements are displayed as either block or inline elements. The default display value can be changed with the display property.

A block element always starts on a new line and takes up all the available width.

An inline element, on the other hand, does not start on a new line, and only takes up as much space as necessary.

inline elements are not allowed to have block elements inside it.

A hybrid type, namely the inline-block element, is like inline elements, but it can have a width and a height - which can be very useful when you want to create a grid of CSS boxes that fills all the width and wraps nicely. The inside of an inline-block element is formatted like a block box.

Care needs to be taken with inline-block elements, because Prince cannot split them over several pages.

The value run-in displays a block element as if it were an inline element at the beginning of the following block element.

With the value list-item, the element is effectively transformed into a list item - for more on lists, please see the chapter Lists.

The value flex enables Flex Layout, while inline-flex makes an element behave like an inline element and lays out its content according to the flex layout model.

Several values refer to Tables, making elements behave as if they were table elements. However, the value inline-table has no direct equivalent in HTML - it behaves like a table HTML element, but as an inline element, rather than a block element. Inside the table box is a block context.

The special value none, which removes the content from the document, is very useful when hiding certain elements in the printed layout.

Transformations

Prince supports CSS transformations of Level 1, with some limitations: it recognizes transform and transform-origin, but does not recognize transform-box. Furthermore, Prince does not allow perspective transforms.

The transform property can be used to rotate, translate, scale or skew an element.

The transform property currently does not affect SVG elements - they need to use their own transform attribute instead (see SVG Transformations).

The transform property function rotate() rotates the element clockwise from its current position. Negative values rotate conter-clockwise.

The function translate() moves an element along a vertical and/or horizontal axis. The functions translatex() and translatey() move the element along one of those axis only. The function translate3d() is supported if the Z (third) coordinate is zero, thus making it equivalent to the 2D translate().

The function scale() affects the size of the element - note that this also alters other properties of an element, such as its font-size, padding, height and width. The functions scalex() and scaley() transform the element in one dimension only.

The functions skewx() and skewy() tilt an element to the left or right. There is no shorthand form.

The origin for the transformations, i.e. the point around which a transformation is applied, can be set with the transform-origin property.

If only one term is given, then the second component is assumed to be center. In particular, if only a percentage or length is given, then it is assumed to be the horizontal coordinate.

If both values are given as keywords, order doesn't matter; but if two coordinates are given and either coordinate is a length or percentage, then the horizontal component must come first: so top 50% is not valid, but top and top center and 50% top are all valid and equivalent.

Lists

A list item has two parts: marker and content.

The content part is rendered inside the list item's border box, and is styled the same way as a normal block, such as div or p element.

The marker positioning is determined by the list-style-position property and is styled using the ::marker pseudo-element.

List markers

The content property can be applied to the ::marker pseudo-element to specify a custom marker for list items.

CSS

li::marker { content: "No. " counter(list-item) }

List marker position

List markers are rendered outside the list item in the left margin area by default. If the CSS property list-style-position has value inside, the marker is rendered as the first inline box inside the list item.

CSS

ol {
    padding-left: 1cm;
    border: solid 2px darkgreen
}
li { border: solid 1px black }
li.inside { list-style-position: inside }
li.outside { list-style-position: outside }

Output

  1. This list item sets the list-style-position to inside, so the list marker is rendered inside the principal box of li.
  2. This list item sets the list-style-position to outside, so the list marker is rendered outside the principal box of li.

When the marker position is outside, it is rendered outside the li principal box. If you want the marker to appear inside the principal box of ol, make sure to give ol enough left padding or li enough left margin.

List marker type

Different list marker types can be chosen by setting the CSS property list-style-type to different values: disc | hyphen | decimal | lower-alpha | ...

The property list-style-type applies to list items and determines the type of marker that they receive. The following table shows examples of some list style types (a table with examples of all supported options for ordered lists, see Counter styles).

decimal 1, 2, 3, ...
decimal-leading-zero 01, 02, 03, ... 09, 10, 11, ...
lower-alpha, lower-latin a, b, c, ... z, aa, ab, ...
upper-alpha, upper-latin A, B, C, ... Z, AA, AB, ...
lower-roman i, ii, iii, iv, v, vi, ...
upper-roman I, II, III, IV, V, VI, ...
asterisks *, **, ***, ...

CSS

li.upper-alpha { list-style-type: upper-alpha }
li.lower-roman { list-style-type: lower-roman }

Output

  1. The marker type of this list item is upper-alpha.
  2. The marker type of this list item is lower-roman.

List marker style

The list marker can also be replaced by an image by using the list-style-image property.

The shorthand property list-style can be used to set the three properties list-style-image, list-style-position and list-style-type together.

Alternatively, the ::marker pseudo-element can be used to style the list item marker, giving full control over its content, width, alignment and so on.

CSS

li::marker { width: 2.4cm }
li.left::marker { text-align: left }
li.center::marker { text-align: center }
li.right::marker { text-align: right }
li.text_marker::marker {
    content: "Number " counter(list-item)
}
li.image_marker::marker {
    content: url("../../image/prince.jpg")
}

Output

Marker example

Tables

Automatic table layout

When the automatic table layout algorithm is used, all contents of the table will be processed to determine the table width and its column width.

The automatic table layout algorithm is used in the following situations:

  • by default; or
  • when table table-layout property is auto; or
  • when table width property is auto, regardless of the value of the table-layout property.

The basic rules used by Prince can be summarized as follows:

  • Uses all contents of a column to calculate its maximum and minimum width. The minimum width typically ensures that the column should be big enough to hold the widest non-breakable unit (for example, a word or an image). The maximum width typically ensures that the column should hold all cell contents without breaking line (unless an explicit line break occurs).
  • If a calculated minimum or maximum column width is smaller than the corresponding specified column width, it will be replaced with the specified column width.
  • If table width has value auto, and if the table fits in the container when using maximum column widths, then maximum column widths will be used. Otherwise, minimum column widths will be used, but they will be adjusted, if the sum of them is smaller than the specified the table width or the container width, so that the table can take up as much space as possible.

Fixed table layout

When the fixed table layout algorithm is used, the table column widths are determined by their specified widths or by the remaining space available, regardless of their contents.

The fixed table layout algorithm is used in the following situations:

  • when the table table-layout property has a value fixed, and
  • the value of width property is not auto
table {
    table-layout: fixed;
    width: 90%
}

Note that if the width property has value auto (which is the default value), the table-layout property will be ignored and automatic table layout will be used instead.

The basic rules used by Prince are as follows:

  • If a column has a specified width, then the specified width is used as its minimum width.
  • For columns that do not have specified widths, the remaining space (specified table width - sum of all the specified column widths) is evenly divided among them as their minimum widths.
  • If the sum of all the minimum column widths is smaller than the specified table width, they will be adjusted to eat up the remaining space.

Separated table borders

When the border-collapse property is set to separate, a table can have separate borders around individual cells. The space between table cell borders is determined by the value of its border-spacing property.

CSS

table {
    border-collapse: separate;
    border-spacing: 5px;
    border: solid 3px black
}
td { border: solid 1px red }
td.dash-blue  { border: 2px dashed blue }
td.solid-green { border: 2px solid green }

Output

A B C
D E F
G H I

Note that by default, the value of border-collapse is separate.

Collapsing table borders

When the CSS property border-collapse is set to collapse, each edge of each cell resolves its final border style and border width based on certain rules.

CSS

table {
    border-collapse: collapse;
    border: solid 3px black
}
table td { border: solid 1px red }
td.dash-blue  { border: 2px dashed blue }
td.solid-green { border: 2px solid green }

Output

A B C
D E F
G H I

Note that the border-spacing property is not used in the collapsing table border model.

The rules used by Prince for choosing the "winner" border are as follows:

  • If a border has a border style of hidden, it beats those with other border styles;
  • Otherwise, if a border has a border style of none, it loses to those with other border styles;
  • Otherwise, if a border has thicker border width, it beats those with thinner ones;
  • Otherwise, a border wins if its border style has higher precedence. The precedence order is: solid, dashed then dotted;
  • Otherwise, a border wins if it is set in a part that has higher precedence. The precedence order is: cell, row, row-group then table.

Cells that span columns

Prince table cells that span multiple columns using the table-column-span CSS property, which takes an integer value and is set to 1 by default.

CSS

td.colspan2 { table-column-span: 2 }

XML

<td class="colspan2"> B </td>

Output

A B
C D E

Cells that span rows

Prince supports table cells that span multiple rows using the table-row-span CSS property, which takes an integer value and is set to 1 by default.

CSS

td.rowspan2 { table-row-span: 2 }

XML

<td class="rowspan2"> A </td>

Output

A B C
D E

Numbering table rows

If you want to number table rows in a table, but there are just too many rows to number by hand, or if the document is dynamically generated and hand numbering is impossible, CSS counters and generated content can help you out:

CSS

table { counter-reset: row }
tr { counter-increment: row }
tr::before {
    content: counter(row);
    display: table-cell
}

HTML

<table>
<tr><td>The First Table Row</td></tr>
<tr><td>The Second Table Row</td></tr>
<tr><td>The Third Table Row</td></tr>
</table>

Output

1 The First Table Row
2 The Second Table Row
3 The Third Table Row

As pseudo-elements only inherit inheritable properties from the element they are attached, non-inheritable properties, such as display and border properties, need to be explicitly set in the pseudo-elements.

Running table headers and footers

When a table spans across more than one page, it might be desirable to have a "running" table header and footer so that they can be carried on to all the subsequent pages on which the table appears.

HTML

<table>
 <thead>
  <tr> <td>Name</td> <td>Mark</td> <td>Grade</td> </tr>
 </thead>
 <tr> <td>Xuehong</td> <td>95</td> <td>H1</td> </tr>
 <!-- other rows for other students -->
 <tfoot>
  <tr> <td>Name</td> <td>Mark</td> <td>Grade</td> </tr>
 </tfoot>
</table>

Rows inside the thead element are used as a running table header. Rows inside the tfoot element are used as a running table footer.

See also Long Tables.

Table captions

Tables can also be provided with a table caption by using the caption HTML element, or by styling an arbitrary element with display: table-caption to be made to behave like caption elements. The caption is positioned above the table by default, but it can be moved to the bottom with the caption-side property.

When a table spans across more than one page, the prince-caption-page property determines whether table captions will be displayed on the first page of a table, or only on the following pages, or repeated on every page that a table appears on. See also Fancy Table Captions.

Columns

Reading long lines of text can be difficult - multiple columns have been used in print for a very long time. CSS allows for clean styling in multiple columns with the help of several properties.

The column-count property specifies the number of columns for the selected element - the column width will be calculated automatically. Alternatively, you can define the (optimal) width of a column with the column-width property, and the number of columns will be defined automatically. Note that Prince might make small adjustments to the actual width in order to use the available space at its best. Both values can also be set simultaneously with the shorthand columns property.

p {
    column-count: 3;
}

The height of the columns is balanced by default, and the text is distributed to the available columns so that the height of the content in each column is approximately equal. In some situations it might be desirable to explicitly determine the height of the columns, creating as many columns as necessary. This is achieved by setting the height or max-height properties on a multi-column block.

With the column-gap property the distance between columns can be styled and the column-rule property allows the addition of a line between columns - this is similar to using border-left or border-right properties.

p {
    column-gap: 2em;
    column-rule: red dotted thin;
}

The column-fill property determines how the content is distributed to fill various columns: the property can be set to auto, filling the columns sequentially, or balance, dividing the content in equal ways between the columns.

When content is laid out in multiple columns, Prince can determine where column breaks are placed in a similar way to breaking content into pages. Use the properties break-before and break-after with the value column to fine tune this behavior.

Prince also supports the properties column-break-before and column-break-after. However, you are encouraged to use the newer properties break-before, break-after with the keyword column from the CSS Fragmentation Module Level 3.

If an element is to break the flow and span several columns, the property column-span helps to achieve this. For floated elements (see Floats) a numeric value tells Prince how many columns the element should span. For non-floated elements that are part of the regular flow of the document, only the keyword all can be used.

The following example instructs Prince to make the h1 heading element span all the columns:

body {
    column-count: 3;
}
h1 {
    column-span: all;
}

Prince features also several column-specific extensions to the float property, namely Page and column floats and Page and column footnotes.

Floats

When printed texts contain images, the text is usually laid out to wrap around those images. To accomplish the same with CSS, the images are floated - either to the left or right of text, or at times even to the top or to the bottom of a column. The float property does just this - it floats an element, allowing the content of other elements to flow around it.

img {
    float: right;
}

The property clear can be considered the float's sister property: an element that has the clear property set on it will not move up, next to the floated element, like the float is asking for. Instead, it will move down after the float.

Prince extends the traditional behavior of floats with a few features that have been ubiquitous in printing for a long time.

Prince extensions to floats

Traditionally, floats move in the inline direction, left or right. Prince extends this behavior with page floats that move in the block direction, specifying that an element should be floated to the top or to the bottom of a page, and with column floats that move the float to the nearest edge of the column in a multi-column layout, with optional column spanning of the float.

This allows for more flexible layout options that meet the needs of formatting documents for print.

Page and column floats

When giving the float property the value top or bottom, the element will be floated to, respectively, the top or the bottom of the page. The values column-top and column-bottom float the element to the top or bottom of the column it appears in, while column-top-corner and column-bottom-corner float the element to the top or bottom of the last column, rather than its natural column. These can be useful if you wanted to create a magazine-style layout, floating an image to the right-hand corner of the current multi-column layout.

img {
    float: column-top-corner;
}

A floated element can span several columns with the help of the column-span property (see Columns). The following example instructs Prince to make the image span two columns:

img {
    float: column-top-corner;
    column-span: 2;
}

The value prince-snap instructs Prince to float the image to the nearest "end", i.e. to the top or bottom of the page, or of the column in the case of a multi-column layout.

img {
    float: prince-snap;
}
Spread floats

In print one typically has to deal with left facing and right facing pages, together forming a spread. To take this into account when placing an element, Prince extends the float property with the values inside and outside, moving the element respectively to the inside or outside of a spread.

If the inside and outside values are used in a multi-column layout, the element is floated to the inside or outside of the column it appears in its natural flow.

Page and column footnotes

The value footnote transforms the element into a footnote: it creates a footnote call in the place where it appears in its natural flow, and moves the element to the bottom of the page. The footnote marker is placed outside of the block of the footnote. With the value inline-footnote, the footnote marker is placed inside of the block of the footnote. Two additional values, namely prince-column-footnote and prince-column-inline-footnote behave in an analogous way, but move the footnote not to the bottom of the page, but to the bottom of its column instead. See also Footnotes.

Conditional modifiers

Prince also takes the additional modifier next. In a multi-column layout, this defers the float to the next column, otherwise it defers the float to the next page.

img {
    float: column-top next;
}

The optional modifier unless-fit is to be used in combination with other float instructions, and expresses a conditional: the element is only floated if it would otherwise cause a page or column break. For example, If you have a large image that happens to occur at the end of the page, it could force a page break and leave a gap at the end of the previous page. So you could float the image top unless-fit, which would move it to the top of the next page unless it fits on the current page without causing a break and leaving a gap:

img {
    float: top unless-fit;
}

Footnotes

Prince supports footnotes using the float property. If an element has the property float: footnote then it will be floated into the footnote area of the page and a reference will be placed in the text.

This example shows some simple footnotes, the fn class is used to create footnotes:

Footnotes example
Footnotes example
Footnotes example

CSS

.fn {
    float: footnote
}

HTML

<p>
Footnotes<span class="fn">A footnote is a note placed at
the bottom of a page of a book or manuscript that comments on or
cites a reference for a designated part of the text.</span>
are essential in printed documents and Prince knows how to generate
them. Most readers will read the footnotes before they read the text
from where the footnotes are anchored<span class="fn">Often,
the most interesting information is found in the footnotes.</span>.
</p>

Each footnote implicitly increments the footnote counter which is used to number the footnotes. The footnote counter can be reset at each new page, section or chapter as necessary. This example resets the counter on each new page.

@page {
    counter-reset: footnote
}

Footnote calls

Footnote calls are the numeric anchors in the text that refer to the footnotes. Prince will generate footnote calls using the ::footnote-call pseudo-element. This is the default style for footnote calls:

*::footnote-call {
    content: counter(footnote);
    font-size: 83%;
    vertical-align: super;
    line-height: none
}

This will display the current value of the footnote counter in a superscript position in a slightly smaller font than the main text. The line-height declaration ensures that the superscript position of the footnote does not affect the line height of the main text.

The footnote call style can be customized to use different fonts or colors. It can even be customized to include different content, such as placing the footnote counter in brackets rather than making it superscript.

*::footnote-call {
    content: "[" counter(footnote) "]";
    font-size: inherit;
    vertical-align: inherit;
}

This rule will generate footnote calls with the number of the footnote in brackets, like this: [1], [2], [3].

Footnote markers

Prince automatically generates footnote markers, the numeric markers placed in front of the footnote text. Footnote markers are similar to the markers added to list items (see Lists) in most respects, and can be styled in a similar fashion using the ::footnote-marker pseudo-element:

*::footnote-marker {
    font-weight: bold
}

This rule will generate footnote markers with a bold font.

Footnote markers are rendered outside the footnote in the left margin area by default. If the CSS property footnote-style-position has value inside, the marker is rendered as the first inline box inside the footnote. This property is similar to the list-style-position property that applies to list markers (see Lists).

Styling and behavior of footnotes

Footnotes are placed within the @footnote area of the page (see Page regions), which can be styled within @page rules.

@page {
    @footnote {
        border-top: solid black thin;
        padding-top: 8pt
    }
}

This rule adds a border and some padding to the top of the footnotes area.

If there are no footnotes on a page, the footnotes area will not be displayed on that page at all.

By default, the @footnote area is at the bottom of the page. However, Prince allows to position the area in different places, effectively offering a mechanism to create simple sidenotes (see Sidenotes).

@page {
    @footnote {
        position: absolute;
        left: 10px;
    }
}

This rule moves the footnotes area to the left side of a page.

Footnotes are created with the float property (see also Floats): an element can be removed from the normal flow of the document by styling it with the footnote value. This creates a footnote call in the place where the element would be in its natural flow, and moves the element's content to the bottom of the page. The footnote marker is rendered outside the footnote in the left margin area, and the footnote is displayed as a block element.

The property footnote-display can be used to change the default display of footnotes: besides the default block display, they can be also treated as inline elements. The value compact leaves it up to Prince to determine whether to display the footnote as a block or inline element: if two or more footnotes fit on one line, they will be treated as inline elements to take up less space.

Making a footnote into an inline element moves the footnote marker into the footnote box as the first inline box inside the footnote.

The float property offers also the value inline-footnote, which is another mechanism to transform the footnote into an inline element.

In a multi-column layout, footnotes can be rendered at the bottom of the page as normal footnotes, or alternatively at the bottom of each column by using the values prince-column-footnote or prince-column-inline-footnote for the float property. See also Prince extensions to floats.

In some situations it might happen that footnotes do not fit on the page on which the footnote call was placed. It might be desirable to tie the footnote to the same page as the call - the prince-footnote-policy can be of help. The following example instructs Prince to move the line with the footnote call to the next page, in order to keep it on the same page as the footnote itself:

p {
  prince-footnote-policy: keep-with-line;
}

Alternatively, the value keep-with-block moves the entire paragraph to the next page.

This property must be applied to the paragraph in which the footnote occurs, not to the footnote element itself.

Flex Layout

Flex layout is a layout model similar to the block layout. It lacks Columns and Floats but gains powerful possibilities to distribute space and align content in a more flexible way. The content of a flex container can alter its height and width to best fill the available space, it can be easily aligned even if the size is unknown or dynamic, and most importantly it can be laid out in any direction, as opposed to the traditional layout models that would either be vertically-based (block layout) or horizontally-based (inline layout).

Prince supports the Flex specification fully, the main limitation currently being page breaks.

In Flex layout some properties apply to the parent element, i.e. to the flex container, while others apply to the children, or flex items.

Flex Containers

To use the flex layout, flex needs to be enabled on the parent element to create the flex container by defining the flex value for the display property.

.flexcontainer {
    display: flex;
}

Next, the direction of the flex layout can be defined by means of the flex-direction property: rightwards, leftwards, downwards, or even upwards! With the flex-wrap property the wrapping of the flex container is controlled - the default is to try to arrange all items on one line. The shorthand property flex-flow can be used to define flex-direction and flex-wrap together.

.flexcontainer {
    display: flex;
    flex-flow: row wrap;
}

The property justify-content defines the alignment of the content along the main axis - extra free space can be distributed in various ways after or before the content, or in specific ways between the flex items. The alignment along the cross axis is controlled with the align-items property. In case there are multiple item lines in a flex container, the alignment of the lines can be controlled with the align-content property. If there is only one line, the property has no effect.

Flex Items

By default, items are placed in the source order inside a flex container, but with the order property it can be modified!

.flexitem1 {
    order: 2;
}
.flexitem2 {
    order: 1;
}
.flexitem3 {
    order: 3;
}

The flex-grow property defines the proportion by which a flex item can grow, if necessary, while flex-shrink defines the proportion by which an item can shrink. The flex-basis property defines the default size of an element, before the remaining space is distributed. However, it is recommended to use the shorthand property flex instead - the value for the flex-grow is mandatory, the other properties are automatically set in an intelligent way.

.flexitem {
    flex: 2;
}

Finally, the property align-self allows the default alignment specified with the align-items property to be overridden for individual flex items.

It is important to know that margins of flex items behave in a slightly special way: margins of adjacent flex items do not collapse, and using the keyword auto for the margins of a flex item will automatically distribute the available space equally around the item - and it will be centered in both axis!

Please notice that percentage values of margins and paddings of flex items are resolved by Prince against the inline axis, i.e. left/right/top/bottom percentages all resolve against width.

Paged Media

Prince produces PDFs - which are a prominent example of paged media. There are a few differences that are crucial to keep in mind when preparing a document for paged media intended for print:

Pagination

The major difference between formatting for the web and for PDF/Print is that PDF is paginated, i.e. the content is placed on discrete pages. Pages have a defined size and content can be laid out in a specific pattern making use of predefined page regions. Elements can not only be floated right and left, but they can also be floated to the top and bottom of the page, or of a column, or the float even can be deferred to the next page (see Prince extensions to floats). Pages can be selected and named, which allows for specific treatment of certain pages. Also, it is important to have an understanding of pagination: content might not fit on a page and might spill over into the next page, or it might be necessary to move it to the next page in order to avoid creating gaps (see also Conditional modifiers).

Page spreads

A basic unit for paged media in print is the page spread: the left page, called verso in a left-to-right script (see Writing Mode), and the right page, called recto, are of the same size and typically are symmetrical to each other and are centered on the gutter. Selected and named pages can be placed recto or verso, and Prince expands several properties and the @page at-rule pseudo-classes with the values verso and recto, or inside and outside, referring to the layout on each page of the spread.

Non-interactive

Last but not least, paged media intended for print is non-interactive by nature. All CSS properties referring to user interaction make no sense, scripting cannot be interactive and scripts need to run before layout is finished. But for these details and scripting after layout please check the section on JavaScript in Printed Media.

Prince allows you to control a number of options that affect how to format pages, from straight-forward options such as page size, to page style, page regions like headers and footers, pagination control and page numbering.

CSS properties that affect pages are specified within page at-rules (see CSS At-rules). For example, we can use the size property within the @page rule to specify the page size (see Page size).

@page {
    size: A4
}

In this section we will show most of the properties that can be specified within a page rule, then we will show how pagination can be controlled and how page styles can be applied to selected pages.

Page size

Page size can be specified using the size property in length units or by a page size keyword (see Page Size Keywords for a list), optionally combined with the portrait or landscape keyword.

/* Use A4 paper */
@page { size: A4 }

/* Use A4 paper in landscape orientation */
@page { size: A4 landscape }

/* These two custom sizes are equivalent */
@page { size: 30cm 40cm }
@page { size: 40cm 30cm landscape }

/* Use square paper, this sets width and height */
@page { size: 30cm }

Sometimes it can be useful to specify the page dimensions in pixels, for example when creating presentation slides (see Presentation slides).

@page {
    size: 1280px 960px;
}

Page style

Pages, like other block level elements, follow the CSS box model introduced in Box Model. Their margin, border, padding and background can be styled within @page rules.

The @page rules can only style the page and its margin boxes - it cannot contain style rules to target specific elements, but it can contain at-rules to target the page regions (for a complete list of possible at-rules, see Page regions).

@page {
    margin: 2cm;
}

Prince also supports the margin-outside and margin-inside properties. These allow you to specify different margins for the inside and outside edges of paper as it is bound into a book. For example it may be necessary to have a larger inside margin (called a gutter) so that after some of the margin is used by the binding, the remaining margins are even.

@page {
    margin: 2cm;
    margin-inside: 3cm;
}

This is used in Fancy headers.

Page regions

Page regions
A page with content in some of its page regions.
A page with content in some of its page regions.

Most content appears inside the page area of one or more pages. Surrounding the page area, but within the margin area, are the page-margin boxes. Other special areas are overlaying the whole page or are placed at the bottom of the page area. Collectively, they are known as the page regions.

This figure shows the positions of some page regions placed in the page margin, called the page-margin boxes. Some of them can be used for creating running page headers and footers.

The @page background is grey and the body's, i.e. the page area's background is white.

The first four page-margin boxes, namely

  • @top,
  • @bottom,
  • @left and
  • @right

are easy to understand and are shown in yellow and red.

Each of these page-margin boxes has a synonym ending in -center or -middle - for instance @top-center is the same as @top, while @left-middle is the same as @left.

You can place content in a page-margin box with the content property.

For example, you can print the current page number at the bottom of each page (see Generated Content):

@page {
    @bottom {
        content: counter(page)
    }
}

Two examples in the next chapter show examples of page headers and footers:

  • the Novel title page example creates a footer to display the page number, but suppresses it for the title page; and
  • the Textbook page numbers example displays a more complex use of headers by placing the book title in the header of left pages, and the current chapter's title in the header of right-facing pages, in addition to the page number.

Several other page regions can also be used. The full list of page regions is shown in the Page regions table.

Page regions
Name Default alignment In figure
text-align vertical-align
@top center middle yellow
@bottom center middle yellow
@left center middle red
@right center middle red
@top-left left middle green
@top-center center middle not shown
@top-right right middle not shown
@bottom-left left middle not shown
@bottom-center center middle not shown
@bottom-right right middle not shown
@left-top center top green
@left-middle center middle not shown
@left-bottom center bottom not shown
@right-top center top not shown
@right-middle center middle not shown
@right-bottom center bottom not shown
@top-left-corner right middle not shown
@top-right-corner left middle blue
@bottom-left-corner right middle not shown
@bottom-right-corner left middle not shown
@page-float-top center top not shown
@page-float-bottom center bottom not shown
@prince-overlay center middle not shown
@footnote left middle not shown

Prince will try to create page regions of the correct sizes. If you need to create boxes of specific sizes you may need to use only a single box (eg: @top) and use the content property to place elements with specific sizes in it.

Note that in the above Page regions figure, Prince leaves space for @top-right and @left-bottom boxes because their counterparts (@top-left and @left-top respectively) have been defined. This keeps the @top and @left centered along the top and side of the page respectively.

The page-margin boxes @top, @top-left or @top-right can be used to create running page headers, and the page-margin boxes @bottom, @bottom-left or @bottom-right are useful for page footers (see Page Headers and Footers).

The page region @prince-overlay is a special region, overlaying all of the page area. A typical use is for creating watermarks on all pages of the document (see Watermarks).

The page region @footnote is placed by default at the foot of the page area and contains the footnotes (see Footnotes). Note that if there are no footnotes on a page, the footnote area will not be displayed on that page at all.

Many CSS properties can be applied to page regions:

  • All of the margin, border, padding and background properties can be used to style page regions.

  • The vertical-align property can be applied to any page region to vertically align its content.

  • When a page region contains generated content, many inline style properties such as color and font can be applied to style the generated content.

The @footnote area can be positioned other than its default position (see Styling and behavior of footnotes and Sidenotes). All other page regions cannot be moved - their position is defined by the page margins.

Generated content in page regions

We have already shown an example of using the page counter to print the page number at the bottom of each page, this is one example of generated content. The page counter is predefined and starts at 1; it increments automatically for each new page. (Note that the page counter cannot be incremented manually using the counter-increment property.)

The page counter can be reset using the counter-reset property at any block-level element within a non-floating element in the normal flow. This is useful for restarting page numbering at a new section of the document.

Restarting page numbering

HTML

<body>
    <div class="front"> cover page, etc, ... </div>
    <div class="contents">
        table of contents, ...
    </div>
    <div class="body">
    <div class="chapter"> chapter 1...</div>
    <div class="chapter"> chapter 2...</div>
    </div>
    <div class=appendix"> appendix1 </div>
    <div class=appendix"> appendix2, ... </div>
</body>

CSS

.contents {
    display: block;
    page: table-of-contents;
    counter-reset: page 1
}
@page table-of-contents {
    @top { content: "Table of Contents" }
    @bottom {
        content: counter(page, lower-alpha)
    }
}

.body {
    display: block;
    page: main;
    counter-reset: page 1
}
@page main {
    @top { content: string(chapter-title) }
    @bottom {
        content: counter(page)
    }
}

.chapter h1 { string-set: chapter-title content() }

Restarting page numbering also uses Named pages which we will explain in more detail below. We create three types of pages: table-of-contents pages, main pages, and pages without a name.

The .contents rule names the pages that it appears on as table-of-contents and resets the page counter to 1 at the start of the contents div. Then the @page rule for those pages generates a page footer that contains the current page number in lower-alpha style. This rule also sets the page header to the string "Table of Contents".

The .body rule names the pages that it appears on as main and resets the page counter to 1 at the start of main div. Then the @page rule for the main pages generates a page footer that contains the current page number in the default decimal style. This rule, together with the .chapter h1 rule, sets the page header to the title of the chapter.

Pages that don't match either of these names have the default style, which does not include a page number in the footer.

In some documents, particularly those that are unbound such as office documents, it can be useful to show the total number of pages on each page. The total number of pages can be accessed using the pages counter. This is a pre-defined counter that is fixed to the total number of pages in the document.

@page {
    @bottom {
        content: "Page " counter(page) " of " counter(pages)
    }
}

This rule will generate page footers such as "Page 1 of 89".

Fancy header example
Image of a page of a textbook or thesis with a header.
This example shows a header as might be found in a textbook. The HTML and PDF are both available. This is a small part of a larger example in our Prince samples repository.
Fancy headers

This example demonstrates a more complete headers style. It uses generated content to print page numbers, the chapter number and title and the section number and title using different styles for left and right pages. It also prints an underline under the header.

@page {
    font-family: Times, Serif;
    font-size: 11pt;
    text-align: justify;
    margin-top: 2cm;
    margin-bottom: 2cm;
    margin-inside: 3.5cm;
    margin-outside: 2.5cm;
}

@page body:left {
    @top-left {
        content: counter(page);
        vertical-align: bottom;
    }
    @top-right {
        content: "Chapter " counter(chapter) ": " string(chapter);
        vertical-align: bottom;
    }
}
@page body:right {
    @top-right {
        content: counter(page);
        vertical-align: bottom;
    }
    @top-left {
        content: counter(chapter) "." counter(section) " "
            string(section);
        vertical-align: bottom;
    }
}
@page body {
    border-top: thin black solid;
}
@page body:first {
    margin-top: 25%;
    @top-left { content: normal; }
    @top-right { content: normal; }
    border: none;
}
@page body:blank {
    @top-left { content: normal; }
    @top-right { content: normal; }
    border: none;
}
body {
    font-family: Times, Serif;
    font-size: 11pt;
    text-align: justify;
    padding: 0.5cm 0cm;
}

div.body {
    page: body;
}

div.body h1 {
    break-before: right;
    prince-page-group: start;
    string-set: chapter content();
    counter-increment: chapter;
    counter-reset: section;
}
div.body h1::before {
    content: "Chapter " counter(chapter) ": ";
}

div.body h2 {
    string-set: section content();
    counter-increment: section;
}
div.body h2::before {
    content: counter(chapter) "." counter(section) " ";
}

The main content area is 2.5cm from the page's edge on all sides. On the left and right this is a margin of 2.5cm and on the top and bottom it's 2cm of margin and 0.5cm of padding. This places the bottom border of the @top page region 0.5cm from the main content area, enough to avoid making it look crowded. The header text has the vertical-align: bottom property to ensure that it appears immediately above the border — the border is made to look like an underline. This example uses many properties and page selectors discussed later in this section. This is a small part of a larger example in our Prince samples repository.

Copying content from the document

Generated content in page regions may contain text content copied from the document using the string-set property:

CSS

@page {
    @top {
        content: string(doctitle)
    }
}

h1 { string-set: doctitle content() }

The @page rule specifies that the top-center page region will contain the text content of the document title copied from the text content of the h1 element in the document.

The second argument to the string() function is a page-policy (see The optional page-policy value).

For a dictionary, you might want to have a page header that says "a-af", where "a" is the first definition on the page and "af" is the last, so you apply string-set for each definition, and then you can select the first and last one with a page policy in the page header.

@page {
  @top-left { content: string(term, first);}
  @top-right { content: string(term, last);}
}

The page policy value first-except is equivalent to start, unless the string-set is applied on the current page, in which case it will return no value.

This can be very useful as a means to repeating the title of a chapter as a page heading in the @top-center page region, without duplicating the information on the page where the heading appears in the running text of the page.

@page {
  @top-center { content: string(letter, first-except);}
}

You can see these examples in full action in the Dictionary sample (HTML - PDF).

Taking elements from the document

Page region content may also be taken from the document itself. Any block-level element can be removed from the normal flow and placed in a page region. It will normally inherit from its original position in the document, but does not display there. Please also note the following:

  • All margin properties of an element not in the natural document flow will be ignored.
  • The first running element that appears on a page will be used on the current page and carried onto following pages, until a new running element is encountered.

To move the content into a page region, the element needs to be removed from the normal document flow position with the running() function of the position property, and inserted into the specified region with the element() function of the content property.

CSS

@page {
    @top { content: element(header) }
}
h1 { position: running(header) }

The @page rule specifies that the top page region is a new running header named "header".

The rule for the h1 element moves it to the "header" running element, removing it from the default normal flow.

Prince also provides another interface for creating running headers: the content can be removed from the normal flow with prince-flow: static(), to be placed in a page region with content: flow().

CSS

@page {
    @bottom { content: flow(footer) }
}
footer { prince-flow: static(footer, start) }

In addition to the standard mechanism, the Prince specific one offers an extra feature that might be useful in certain scenarios: the static() function accepts an optional start argument, which makes the fetched content available, as if it were fetched from the start of the document. An example to clarify:

Many HTML documents designed for browsers have the following structure:

<header>
main content
<footer>

Unfortunately, if you want to place the footer element in the page footer, it will only appear on the last page - because it is at the end of the document! To solve this, the document must be modified to look like this:

<header>
<footer>
main content

It can be achieved by using JavaScript to move the element, but the simple start keyword on the prince-flow property instructs Prince to pretend that the element was seen at the beginning of the document.

The element() and flow() functions replace the entire margin box, and cannot be combined with other content. If you just want to capture some text from the document, use named strings instead (see Copying content from the document) - they can be combined with other content.

Selecting pages

It is often necessary to apply styles to some pages, but not others. Either applying them to only some pages, or on every page except selected pages. CSS and Prince provide a number of page selectors for choosing which pages a rule applies to.

In a novel it is useful to print a page number at the bottom of every page, except for some pages such as the title page. In this example the @page rule is applied to all pages. Then the @page:first rule, which is more specific, removes the footer from the first page. See Page regions and Generated Content.

Novel title page example
Novel title page example image.
A title page example showing use of @page:first. Download the PDF or the HTML.
<html>
<head>
<style>
@page {
    @bottom {
        content: counter(page)
    }
}
@page:first {
    margin-top: 10cm;
    @bottom {
        content: normal
    }
}
h1, h2.subtitle {
    text-align: center
}
h2.chaptertitle {
    break-before: page
}
</style>
</head>
<body>

<h1>The Magnificent Octopus</h1>
<h2 class="subtitle">S. Baldrick</h2>

<h2 class="chaptertitle">Chapter 1</h2>
<p>Once upon a time there lived a little saussage.</p>

</body>
</html>

In this example the @page rule specifies styles that apply to all pages: Then the @page:first rule overrides this for the first page only. It resets the content property for the footer and increases the top margin, printing the title of the novel in a reasonable place on the page (see Page style). This example also uses the break-before property to force a page break (see Page breaks).

When using the :first page selector to choose the first page in each chapter (such as in Fancy headers) it may be necessary to add prince-page-group: start to the first element in each chapter (such as h1). See Page groups.

The :left and :right page selectors can be used to style left and right pages in a bound book differently. This is often used in text books to place the page number on the outside top corners of pages.

Alternatively, the :recto and :verso selectors can be used, with the advantage of being independent of directionality of the script: in a left-to-right script, :recto is the right-hand side of a spread, and :verso is the left-hand side, while in a right-to-left script these values are inverted: :recto defines the left-hand side of a spread, and :verso defines the right-hand side. See also Writing Mode.

Textbook page numbers example
Textbook page numbers example image.
A text book example showing use of @page:left and @page:right. Download the PDF or the HTML.
@page:left {
    @top-left { content: counter(page) }
    @top-right { content: string(book-title) }
    margin-left: 2cm;
    margin-right: 3cm;
}
@page:right {
    @top-left { content: string(chapter-title) }
    @top-right { content: counter(page) }
    margin-left: 3cm;
    margin-right: 2cm;
}

h1 { string-set: book-title content() }
h2 { string-set: chapter-title content() }

These rules also place the book title in the header of left pages, and the current chapter's title in the header of right-facing pages. The book title is copied from the text content of the h1 element while the chapter title is copied from the text content of the h2 elements (see Generated Content). They also specify wider margins in the gutter of the page spread; binders may need this extra width for a book's binding.

The first page in a document using the default left-to-right reading order is a right page. Imagine the cover or a title page of a book which appear on a right page. The first page of a right-to-left document is a left page.

By putting break-before: left or right at the very beginning of the document, it will not leave a blank page, but instead will change whether the document begins on a left or right facing page.

Sometimes it can be useful to select the Nth page in a document. The :nth(N) page selector can be used to do this:

@page:nth(42) {
    ...
}

Named pages

Sometimes it is necessary to style pages depending on their content; named pages allow us to select pages that contain particular elements. We used this in Restarting page numbering, to apply a style to the table of contents pages to print their page numbers using roman numerals.

The element containing the table of contents has a page property applied, specifying that this element's pages are table-of-contents pages. The page property may be applied to any block-level element within a non-floating environment in the normal flow.

.contents {
    display: block;
    page: table-of-contents;
}

Then using this page name to apply a different @page rule to the table-of-contents pages:

@page table-of-contents {
    @top { content: "Table of Contents" }
    @bottom {
        content: counter(page, lower-alpha)
    }
}

More than one element can belong to the same name, in other words, page names behave like CSS classes.

Prince will create a page break between elements belonging to different named pages, including elements without a named page. So in Restarting page numbering, a page break will be inserted after the the table of contents, because the next element has the page name main rather than table-of-contents.

Selectors such as :first, :Nth, :left and :right also work with named pages. For example:

@page preface {
    @bottom {
        content: counter(page, lower-alpha)
    }
}
@page preface:first {
    @bottom {
        content: normal;
    }
}

This example only works when a page name is used only once within a document, such as for the preface of a document (documents only have one preface). If you wish to apply a style to the first page of every chapter then you must use the prince-page-group property to create page groups:

div.chapter {
    page: chapter;
    break-before: right;
    prince-page-group: start;
}
@page chapter {
    @bottom {
        content: counter(page);
    }
}
@page chapter:first {
    @bottom {
        content: normal;
    }
}

The property prince-page-group: start instructs Prince to start a new page group. This is necessary for the div.chapter:first selector to match the first page of each chapter, instead of only the first page in the first chapter. See Page groups.

Blank pages

A special case are blank pages.

As we discussed in the previous section, break-before: right can be used to place the first page of a chapter on the right page in a spread. If the previous page is a right page, two page breaks are inserted, leaving a blank left page. However, this page will have normal @page styles applied to it, which is usually not what people want. The :blank page selector can be used to change the style of blank pages, pages skipped such as a left page before a break-before: right, including removing any content.

@page:left {
    @top-left {
        content: counter(page);
    }
}
@page:right {
    @top-right {
        content: counter(page);
    }
}

@page:blank {
    @top-left {
        content: normal;
    }
    @top-right {
        content: normal;
    }
}

h1 {
    break-before: right;
}

This example clears the generated content used on these pages. This works because :blank is more specific than either :left or :right. The :blank page selector can also be used with named pages.

@page frontmatter {
    @bottom { content: counter(page, lower-roman); }
}

@page frontmatter:blank {
    @bottom { content: normal; }
}

If chapter 1 also resets page numbering, then the page numbers will be reset on the first content page, i.e. a non-blank page.

It is not always desirable to have no content on blank pages. Sometimes otherwise blank pages are required have some content, such as a notice saying "This page intentionally left blank". For example, in legal documents, this prevents people from mistaking a dangerous printing error for an intentionally blank page.

Page groups

When consecutive elements belong to the same named page but logically separate structures (such as individual chapters) Prince combines them into one page group. This causes it to apply the :first page selector to the first page of the whole page group only (the first page of chapter 1). Instead we usually want :first applied to the first page of each chapter.

This can happen either:

  • when chapters are separated by an element, such as h1 which may have break-before: right applied (this can be seen in Fancy headers);
  • or when each chapter is a block element such as a div.

Prince provides the prince-page-group property that can be used to start a new page group. It can be seen in Fancy headers applied to h1 elements in the body of the document.

div.body h1 {
    break-before: right;
    prince-page-group: start;
    ...
}

prince-page-group also forces a page break, overriding any properties that attempt to avoid page breaks. The more specific left and right page take precedence over prince-page-group.

Controlling pagination

Prince will create page breaks automatically when new content will not fit on a page. Sometimes it is useful or necessary to control where page breaks should and should not be used. There are two ways to do this, and both are useful in different circumstances: page breaks can be added or prohibited with the Page breaks properties, and you can control where, within a paragraph, a page break may occur with the Widows and orphans properties.

Page breaks

The simplest case is when you want to explicitly create a page break. This is typically used at the beginning of a chapter, to start the new chapter on a new page.

h1 {
    break-before: page;
}

break-before is used to force a page break immediately before an h1 element, New chapters are often started on the recto pages in text books, this is usually the right page:

h1 {
    break-before: right
}

Other values are auto, avoid, avoid-page, avoid-column, left, as well as recto, verso and column.

The previous example could therefore also have been written in the following, more semantic (and possibly more flexible) way:

h1 {
    break-before: recto
}

The property break-after may also be used to force a page break after an element.

Presentation slides
Presentation slides example
A title page slide for a presentation, with a title and          subtitle. An example of an overhead slide for a presentation.             It has a title and a single paragraph.
Two overhead slides for a presentation. The slides use white on black for better contrast on most projectors, and a 4x3 aspect ratio. Download the PDF or the HTML and CSS.

It is necessary to force a page break when creating overhead slides. This can be done by placing the content for each slide in a <div class="slide"> and using break-before: page as shown below. This example shows other styling that may be required to create presentation slides.

CSS

@page {
    size: 1280px 960px;
    @bottom-left {
        content: "Presentation Title";
    }
    @bottom-right {
        content: counter(page);
    }
    background: black;
    color: white;
    font-family: DejaVu Sans, sans-serif;
    font-size: 16pt;
    margin: 96px;
}

@page:first {
    @bottom-left { content: normal }
    @bottom-right { content: normal }
}

div.centerpage {
    /*
     * Cause the content on these pages to begin part-way through
     * the page. This is useful for a title page.
     */
    margin-top: 33%;
}

body {
    font-size: 28pt;
    font-family: DejaVu Sans, sans-serif;
    color: white;
}

div.slide {
    break-before: page;
}

HTML

<div class="slide">
  <h2>Slide Title</h2>

  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
    eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
    ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
    aliquip ex ea commodo consequat. Duis aute irure dolor in
    reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
    pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
    culpa qui officia deserunt mollit anim id est laborum.
  </p>
</div>

The font-family and color properties are specified both in the @page and body rules, even though they're the same. This is required because the page regions are outside of the body and must be styled separately, likewise the content within body cannot be styled by the @page rule.

A rendered slide for this example is shown in Presentation slides example . The example has been adapted from slides (HTML+CSS) for a presentation about the Mercury programming language. This is part of our samples repository. You are encouraged to use samples from the repository and contribute your own.

So far we have discussed forcing a page break, however suppressing page breaks is also important. For example, it is poor style to have a page break between a header and the first paragraph of a section. Therefore, the default Prince stylesheet will use the break-after property to suppress page breaks immediately after headers:

h1, h2, h3, h4, h5, h6 {
    break-after: avoid
}

If a heading occurs at the bottom of a page, it may be moved to the next page to keep it with the content that follows it, usually a paragraph.

Avoiding page breaks within an element is also important. For example, it is best to avoid breaks within a figure or table. This can be done with the break-inside property:

.figure, table {
    break-inside: avoid
}

If the figure or table would have been split across two pages, it may be moved to the next page to keep it in one piece. An element longer than one page will still need to be split across multiple pages.

The break-inside property cannot be used to create forced page breaks; its only valid values are auto and avoid.

These three properties can be applied to block-level elements, table rows and table row groups that occur within an in-flow element (ie. inside the normal flow of the document, not inside a float or an absolutely positioned block). Therefore the figure and table example only make sense when the figure or table is not floated.

Prince also supports the properties page-break-before, page-break-after and page-break-inside from the CSS 2.1 specification. However, you are encouraged to use the newer properties break-before, break-after and break-inside from the CSS Fragmentation Module Level 3.

Page breaks have similarities with column breaks, see Columns.

Page breaks and decoration

When a page (or column) break occurs within a box (such as a div) its bottom and top borders are cloned so that they also appear at the bottom of the first section and the top of the second section of the box. This is shown in the left of Box decoration break sample. This is the default but may be set with the box-decoration-break property, setting its value to clone.

Box decoration break sample
The box on the left is completely enclosed by its border       (clone);       while the box on the right has no border at the bottom where it       wraps onto the next page (slice).
This figure shows the result of using the box-decoration-break property. On the left the clone value is used while on the right slice is used. The PDF and HTML are available for download.
div.box1 {
    box-decoration-break: clone
}

If instead you wish the borders to remain open, as if the box were simply sliced in half, as in the right of Box decoration break sample, then you can set this property to slice.

div.box2 {
    box-decoration-break: slice
}

Widows and orphans

Just as breaking a page between a heading and the first paragraph below the heading can look bad, breaking the page after only one or two lines of a paragraph also looks bad. These stray lines are called orphans. The minimum number of orphans to allow can be specified with the orphans property (the default is 1).

p {
    orphans: 2
}

Likewise the minimum number of lines to move to a new page (widows) can be specified with the widows property (the default is 1).

p {
    widows: 2
}

It can be easy to confuse widows and orphans. However a mnemonic device can help: "An orphan is alone from the beginning [of the paragraph]; a widow is alone at the end [of the paragraph]". (Source Widows and orphans — Wikipedia).

Trimming marks

When typesetting a magazine or flier it can be useful to print right to the edge of the paper. However most printers will refuse do do this. It is better to print on larger stock and then crop the paper to the correct size. If you use the marks property, Prince will create bleed and trim areas around your content (and the declared page size). This can be seen in the catalog example, adapted from the Catalog sample in the Prince samples repository.

Furniture catalogue example
Furniture catalogue with bleed and trim areas for printing and       cropping.  The background image is larger than the page (but not the       paper), by cutting where the crop marks indicate the background image       extends right to the edge of the page.
The furniture catalogue with bleed and trim areas for printing and cropping. Download the PDF or the HTML and CSS.
@page{
    size: 8.5in 10.5in;
    margin: 0;
    background: url("images/CatalogueCover.jpg");
    background-position: center;
    background-size: 104%;
    background-repeat: no-repeat;
    marks: crop cross;
    prince-bleed: 0.25in;
    prince-trim: 0.25in;
}

This example uses some of the properties that we introduced above, plus three new ones: marks, prince-bleed and prince-trim. These options enable crop and cross marks and specify bleed and trim areas. Note that size of the content does not change when we add these options, the page is still 8.5in by 10.5in as specified by the size property. Instead 0.25in of bleed area and 0.25in of trim area has been added to each edge (1in total). Therefore we will need to print on 9.5in by 11.5in paper. Prince will print solid background colors and repeating pictures into the bleed area - we set the background size to 104% so that it would print into the bleed area.

Prince also allows the placement, length and width of the crop marks to be specified respectively with the prince-mark-offset, prince-mark-length and prince-mark-width properties.

Generated Content

Generated content is text and other content that is not found in the original input document, but is added to the output from a style sheet using the CSS content property. Useful applications of this property include Page regions, List markers or Footnotes.

Generated Content Functions

Generated content is inserted by means of several functions that typically are used within the content property. However, please note that these functions are not unique to the content property, but can be used for the same purpose in several other ones, namely:

  • content
  • prince-bookmark-label
  • prince-pdf-page-label
  • prince-tooltip
  • string-set

See also the section on CSS Functional Expressions for additional details on these functions.

The most simple use of generating content in these properties is to insert a literal string. A literal string can also be passed as an argument to the leader() function, which expands to fill the available space on the line like justified text, by repeating the string as many times as necessary.

The properties can also insert external content fetched from another resource. This can be done with the following functions:

  • the url(url) function, returning the text content at the given URL,
  • the target-content(url) function, referencing the text content of the linked element (see Using target-content()), or
  • the prince-base-url() function, returning the base URL of the current document.

It can also be done with the prince-fallback(url) function, which works just like the url() function, but also has the possibility of specifying a fallback content, in case the loading of the URL should fail.

The content to be inserted can also be fetched from the attributes of other elements with the attr(attribute-name) function, or from other elements with the following mechanisms:

  • Any block-level element can be removed from the normal document flow, to be inserted in a page region: it is best removed with the position property and its running(name) function, and inserted with the element(name) function. Alternatively, it can be removed with the prince-flow property, to be inserted with the flow(name) function. See the documentation for Taking elements from the document for more details.
  • An element can be referenced with the string(ident) function after having been defined in the string-set property with the content() function. This does not remove the element from the natural document flow, but instead copies it into the page region. See Copying content from the document.

The following functions can also be used for different forms of counters:

  • the counter(name) function generates a value for the innermost counter,
  • the counters(name, "separator") function concatenates counters on all levels;
  • the target-counter(url, counter) function retrieves the value of the innermost counter with a given name at the given URL, and
  • the target-counters(url, counter, "separator") function retrieves the value of all counters of a given name from the end of the given URL.

All counter functions can take an optional argument to define the counter style (see Counter styles). Prince also offers two mechanisms to create user-defined counter styles: either by means of the prince-script() function (see below, and User-defined counter styles), or by means of the generated content functions repeat(string+), defining a sequentially repeated pattern for numbering the items, or symbols(string+), defining the symbols used for numbering the items.

Last but not least, Prince supports arbitrary JavaScript functions to be called from CSS generated content using the prince-script() function (see Script Functions).

A special function is prince-glyph-index(int), which allows to choose a glyph from a font by the index of that glyph in the font. Note that this is very non-portable, as glyph indices are specific to individual font versions. But it is a possible escape hatch for people who need a specific glyph and don't have any other way of accessing it (by Unicode character or OpenType substitution).

The optional page-policy value

The generated content functions element(), counter(), counters(), string() and flow(), have a second, optional argument, namely page-policy, which can be one of the following:

start
defining the value the counter had at the start of the page (eg. the last value it was set to on the previous page);
first
defining the first value the counter was set to on this page, or the same as start if the counter was not set on this page;
first-except
defining the first value the counter was set to on this page, or no value at all if it was set on this page;
last
defining the last value the counter was set to on this page, or the same as start if the counter was not set on this page.

The page policy values of the string() function are only meaningful for string() used in page region content.

For a good example of its use, please see Copying content from the document.

Before and After pseudo-elements

The content property can be applied to the ::before and ::after pseudo-elements to add generated content before or after an element. For example, adding section numbers in front of headings or including quotation marks around a block of text.

CSS

h1::before, h1::after { content: "***" }

This will place three asterisks before and after h1 elements.

Counters and Numbering

Counters are the mechanism provided by CSS to perform numbering. They can be used to number list items, pages, footnotes, sections and any other document content that needs to be numbered.

Initializing and incrementing counters

To use a counter, it first needs to be initialized with the counter-reset property, which can be applied to any element and initializes one or more counters to the specified values, or to zero if no value is specified. The property can be used to reset a counter by re-initializing it.

Unless the resetting of a counter creates a nested counter, the scope of the counter includes the current element and all of its following siblings.

The counter-increment property applies to any element and increments or decrements one or more counters by the specified values, or by one if no value is specified.

The counter-increment and counter-reset properties are ignored on elements whose display property has the value none.

Displaying counters

Once initialized, a counter can be displayed with either the counter() or counters() function in a content property.

The counter() function generates a value for the innermost counter, formatted in the optional counter style (decimal by default - see Counter styles).

The counters() function concatenates counters on different levels, separated with the separator string and formatted in the optional counter style (decimal by default - see Counter styles).

CSS

div.example1 { counter-reset: h3 h4 }
div.example1 h3 { counter-increment: h3 }
div.example1 h4 { counter-increment: h4 }
div.example1 h3::before { content: counter(h3) }
div.example1 h4::before {
    content: counter(h4, lower-alpha)
}

This creates two counters inside the scope of a div element. All h3 and h4 heading elements will be numbered starting from 1 and the counter number will be placed before the heading text.

CSS

div.example2 { counter-reset: h3 }
div.example2 h3 {
    counter-increment: h3;
    counter-reset: h4
}
div.example2 h4 { counter-increment: h4 }
div.example2 h3::before { content: counter(h3) }
div.example2 h4::before {
    counter(h4, lower-alpha)
}

In this example the h4 counter will be reset at each h3 element, to produce sub-section numbering that restarts at each new section.

Nested counters

If a counter is reset on an element and the same counter has also been reset on an ancestor of that element, a nested counter will be created. The scope of the nested counter is the current element only and its final value will not be carried onto its following siblings.

For example, a nested XHTML list with a ul element inside a li inside another ul creates a nested list-item counter.

CSS

ol { counter-reset: list-item }
li { counter-increment: list-item }
li::marker {
    content: counters(list-item, ".", decimal);
    color: brown;
    font-weight: bold
}

Counter styles

Counter values are displayed as decimal numbers by default, but they may be displayed using other styles such as roman numerals or consecutive letters of the alphabet.

CSS

chapter { counter-increment: chapter-num }

chapter::before {
    content: "Chapter " counter(chapter-num, upper-roman)
}

This rule will generate text such as "Chapter IV" before each chapter, with the appropriate chapter number displayed in uppercase roman numerals.

The following table shows examples of the various counter styles:

decimal 1, 2, 3, … 9, 10, 11, …
decimal-leading-zero 01, 02, 03, … 09, 10, 11, …
lower-roman i, ii, iii, iv, v, vi, …
upper-roman I, II, III, IV, V, VI, …
lower-alpha, lower-latin a, b, c, … z, aa, ab, …
upper-alpha, upper-latin A, B, C, … Z, AA, AB, …
asterisks *, **, ***, ****, …
lower-hexadecimal 1, 2, 3, … 9, a, b, c, …
upper-hexadecimal 1, 2, 3, … 9, A, B, C, …
octal 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, …
binary 1, 10, 11, 100, 101, 110, 111, …
arabic-indic ١, ٢, ٣, ٤, ٥, ٦, …
lower-greek α, β, γ, …, ι, κ, λ, …
upper-greek Α, Β, Γ, …, Ι, Κ, Λ, …
persian / urdu ۱, ۲, ۳, ۴, ۵, ۶, …
cjk-decimal 一, 二, 三, 四, 五, 六, …
japanese-informal 一, 二, 三, 四, 五, 六, …
simp-chinese-informal 一, 二, 三, 四, 五, 六, …
trad-chinese-informal 一, 二, 三, 四, 五, 六, …
japanese-formal 壱, 弐, 参, 四, 五, 六, …
simp-chinese-formal 壹, 贰, 叁, 肆, 伍, 陆, …
trad-chinese-formal 壹, 貳, 參, 肆, 伍, 陸, …
lower-norwegian a, b, c, … z, æ, ø, å, aa, ab, …
upper-norwegian A, B, C, … Z, Æ, Ø, Å, AA, AB, …
lower-russian а, б, в, г, д, е, ж, …
upper-russian А, Б, В, Г, Д, Е, Ж, …
lower-ukranian а, б, в, г, д, е, є, …
upper-ukranian А, Б, В, Г, Д, Е, Є, …
lower-belarusian а, б, в, г, д, е, ж, …
upper-belarusian А, Б, В, Г, Д, Е, Ж, …
lower-bulgarian а, б, в, г, д, е, ж, …
upper-bulgarian А, Б, В, Г, Д, Е, Ж, …
lower-serbian а, б, в, г, д, ђ, е, …
upper-serbian А, Б, В, Г, Д, Ђ, Е, …
repeat(x, y, z) x, y, z, xx, yy, zz, xxx, yyy, …
symbols(x, y, z) x, y, z, 4, 5, 6, …

See also User-defined counter styles for custom counters.

Cross-references

Prince supports cross-references using generated content with two special functions: target-counter() and target-content().

Using target-counter()

The target-counter() function can be used with the content property to reference the value of a counter at a linked element.

CSS

a[href]::after {
    content: " [See page " target-counter(attr(href), page) "]"
}

This will add a cross-reference after every link with the correct page number determined automatically. For example: [See page 17].

The target-counter() function can specify any counter, allowing cross-references to refer to list items, chapters or sections as well as pages.

The target-counter() function can also take an optional counter style, similar to the normal counter function.

CSS

a[href]::after {
    content: " [See chapter "
	     target-counter(attr(href), chapter, upper-roman)
	     "]"
}

This will add a cross-reference after every link with the correct chapter number determined automatically and displayed using roman numerals. For example: [See chapter IV].

Using target-content()

The target-content() function can be used with the content property to reference the text content of a linked element.

CSS

a[href]::after {
    content: " [See '" target-content(attr(href)) "']"
}

This will add a cross-reference after every link that includes the text of the element being linked to, such as a chapter title. For example: [See 'Introduction'].

Script Functions

Prince supports arbitrary JavaScript functions to be called from CSS generated content using the prince-script() function (see the content property). To make the functions available to CSS, the Prince.addScriptFunc method is used (see The Prince Object).

Please note that Prince is not running JavaScript by default - it needs to be explicitly enabled. See Applying JavaScript in Prince.

CSS

p::after {
    content: prince-script(myfunc)
}

JavaScript

function myfunc()
{
    return "Some generated content text!";
}

Prince.addScriptFunc("myfunc", myfunc);

Accessing the current date and time

JavaScript functions have access to the current date and time, which can be added to the document using prince-script() in generated content.

CSS

@page {
    @top {
	content: prince-script(datestamp)
    }
}

JavaScript

Prince.addScriptFunc("datestamp", function() {
    return (new Date()).toString();
});

User-defined counter styles

The JavaScript functions used with prince-script() can take arguments that are themselves generated content. This allows functions to operate on counter values and implement new counter styles.

CSS

li::marker {
    content: prince-script(mycounterstyle, counter(list-item))
}

JavaScript

Prince.addScriptFunc("mycounterstyle", function(n) {
    if (n == 1) return "one";
    else if (n == 2) return "two";
    else if (n == 3) return "three";
    else return n;
});

For another way of creating user-defined counter styles, see Generated Content Functions.

Scripting

JavaScript can be used to transform documents by generating tables of contents and indices, sorting tables, rendering charts and graphs, and other tasks that go beyond the scope of CSS.

Scripts can access and modify the input document using the W3C standard DOM (Document Object Model). Prince also supports some additional properties and methods described below.

Please note that Prince is not running JavaScript by default - it needs to be explicitly enabled. See Applying JavaScript in Prince.

JavaScript in Printed Media

Prince is a user agent producing primarily documents meant to be printed, and as such, some limitations are in place that set it apart from most other user agents that support JavaScript.

The most notable difference is the fact that a printed page cannot be interactive, being static in nature: a document cannot be modified after it is deemed to be ready for print. JavaScript can be run twice only: the first time it is run before layout, where it interacts with and modifies the layout (and the DOM structure). Once layout is finished, JavaScript can be run a second time from the complete event handler (see Event Handling). However, this time it is only allowed to inspect the layout and cannot modify the DOM. See also The "Two-Pass" Solution.

A consequence of the non-interactive nature of printed media is that any interactive events, such as e.g. onClick, do not make sense, and will never fire.

Prince allows also for scripts to be passed directly to the PDF, to be executed when the PDF file is opened. The prince-pdf-script property is used for this purpose. A common use case is to activate the "Print" dialog automatically. See also PDF Actions.

JavaScript in Prince

Prince supports most of ECMAScript 5th edition (ES5), but not strict mode. Later editions of ECMAScript are not supported.

A full list of all supported JavaScript objects, methods and properties can be found in the References section in JavaScript Support. Here we shall just illustrate a few highlights from Prince's JavaScript support.

Logging

The Prince log can be accessed from JavaScript via the Log object (also available as Prince.Log), which has the following methods:

Log.info("message")
Log.warning("message")
Log.error("message")
Log.data("name", "value")

Console Access

When running Prince from the command-line, the console object can be used to write messages directly to the terminal:

console.log("Hello, world!")

Console access is only supported when running Prince directly from the command-line, and should not be used when calling Prince through a server wrapper or graphical user interface.

Event Handling

When the document has been fully parsed and is ready for processing, Prince will fire the DOMContentLoaded and load events on the window object.

These load events can be captured by setting the onload attribute on the body element in HTML documents, or by setting the window.onload property or calling window.addEventListener.

When document conversion has finished, Prince will fire the complete event on the Prince object. This event can be captured by calling Prince.addEventListener, and is useful for logging document statistics, or for using the output for The "Two-Pass" Solution.

When multiple documents are processed into one PDF, the complete event will only fire once, on the first document.

User interface events such as onclick are not supported by Prince.

Document Statistics

The Prince.pageCount property can be accessed after document conversion has finished, then logged as data for the calling process to access:

function logPageCount()
{
    Log.data("total-page-count", Prince.pageCount);
}

Prince.addEventListener("complete", logPageCount, false);

See also The "Two-Pass" Solution for another use of accessing document properties after the document conversion has finished.

The Prince Object

The Prince object can be used to control various scripting aspects in Prince.

Prince.addScriptFunc(name, function)
Prince.trackBoxes = (boolean)
Prince.convertToFile(JSON, OutputFileName, ...optional extra job resources)
Prince.convertToBuffer(JSON, ...optional extra job resources)

The Prince.addScriptFunc method takes two arguments: the string name that will be exposed to CSS, and the function itself. See Script Functions for an example.

Prince.trackBoxes is a bool that will enable the box tracking API if set to true, so that it can be used later in the complete event. See The Box Tracking API.

The Prince.convertToFile and Prince.convertToBuffer methods allow you to start new Prince jobs:

convertToFile(JSON, OutputFileName, ...optional extra job resources)

- returns bool indicating success

convertToBuffer(JSON, ...optional extra job resources)

- returns ArrayBuffer if successful, null if not

Whereby JSON is a job description similar to the one specified in the Prince Control Protocol, while the optional extra job resource arguments are ArrayBuffers or strings that can be referenced from the JSON using the job-resource: URLs. See Prince Control Protocol.

The PDF Object

The PDF object can be used to specify PDF properties and settings, including attaching extra files to the generated PDF, similar to the --attach command-line argument:

PDF.attachFile(url, description?)

PDF.attachFile("data.xls", "Latest sales figures.");

Other PDF properties, which are set by assignment, include:

PDF.embedFonts = (boolean)
PDF.subsetFonts = (boolean)
PDF.artificialFonts = (boolean)

PDF.compress = (boolean)

PDF.encrypt = (boolean)
PDF.userPassword, PDF.ownerPassword = (string, can be null)
PDF.allowPrint, PDF.allowModify, PDF.allowCopy, PDF.allowAnnotate = (boolean)
PDF.keyBits = "40" | "128"

PDF.script = (string, can be null)
PDF.openAction = (eg. "print")
PDF.pageLayout = "single-page" | "one-column" | "two-column[-left/right]"
PDF.pageMode = "auto" | "show-bookmarks" | "fullscreen" | "show-attachments"
PDF.printScaling = "auto" | "none"
PDF.duplex = "auto" | "simplex" | "duplex-flip-short-edge" | "duplex-flip-long-edge"

PDF.profile = (string, can be null)
PDF.outputIntent = (URL string, can be null)

PDF.objectStreams = (boolean)

PDF.title
PDF.subject
PDF.author
PDF.keywords
PDF.creator

PDF.lang

There is one more PDF object not mentioned so far: the PDF.pages object is different from all preceding PDF objects - the latter ones are set before document conversion begins, while the former becomes available only after the complete event (see Event Handling) and returns a list of boxes - see The Box Tracking API.

The Box Tracking API

The box tracking API must be enabled with Prince.trackBoxes before formatting starts.

Prince.trackBoxes = true;

It then becomes available in the complete event (see Event Handling), when you can call the getPrinceBoxes() method while iterating through the required DOM elements, to return a list of boxes.

Prince.addEventListener("complete", function() {
  var xs = document.getElementsByTagName("ins");
  for (var i = 0; i < xs.length; ++i)
    {
      var ins = xs[i];
      var boxes = ins.getPrinceBoxes();
    }
}, false);

The PDF.pages array mentioned earlier (see The PDF Object) also is available only after the complete event and also returns a list of boxes (see Page regions).

function printbox(str,box) {
  console.log("");
  for (var i in box) {
    console.log(str+i+": "+box[i]);
  }
  for (var i=0; i<box.children.length; i++) {
    printbox(str+"  ",box.children[i]);
  }
}

Prince.addEventListener("complete", function() {
  var pages = PDF.pages;
  for (var i = 0; i<pages.length; ++i)
    {
      console.log("PAGE "+(i+1)+" HAS THESE BOXES");
      printbox("  ",pages[i]);
    }
}, false);

Boxes are JavaScript objects with some or all of the following properties:

type =     "BODY" |
           "COLUMN" |
           "FLEXLINE" |
           "FOOTNOTES" |
           "FLOATS" |
           "BOX" |
           "LINE" |
           "SPAN" |
           "TEXT" |
           "SVG" |
           "IMAGE"
pageNum =  the page of the current box
x =        x-coordinate, in pt
y =        y-coordinate, in pt (set to zero on some boxes)
w =        width, in pt
h =        height, in pt (set to zero on some boxes)
children = array of child boxes
parent =   parent box
element =  DOM element for box (may be null)
pseudo =   pseudo-element name or null
text =     string
src =      URL string for images
style =    CSS style object for box

The x, y, w and h measures, defining respectively the x- and y-coordinates and the width and height of the box, use the same coordinate system as the PDF, i.e. the box tracking units are measured in points (pt) and the origin is the lower left corner of the page.

The box with the value BODY represents the page area returned by PDF.pages (and thus is not necessarily equivalent with the body element); the content of the page-margin boxes is not included in the tree (see Page regions for the definition of page area and page-margin boxes).

The properties of a box can be queried with the BoxInfo() method.

Since the box tracking API is available only after the complete event, it cannot be used to modify the document (see JavaScript in Printed Media).

However, see The "Two-Pass" Solution for making use of its output. Two further sample applications of the box tracking API can be seen in the Changebars example, and in Detecting Overflow.

Unsupported DOM Properties

The following DOM properties are not supported in Prince:

document.write
window.setInterval

Graphics

Prince supports a wide range of graphic features, treated in more detail in the following sections. RGB, RGBA, HSL, HSLA, CMYK, and named spot colors are supported, and so is color management. Bitmap images and SVG are supported.

Color

Prince supports RGB, RGBA, CMYK, HSL, HSLA and named spot colors. For Prince's color management, please see the Color Management section.

Prince understands CSS basic color names as well as the list of extended color keywords from the CSS Color Module Level 4. It also supports the keywords transparent and currentColor.

RGB(A)

To use an RGB color in CSS, it can be expressed either as a value in hexadecimal notation, as an rgb() function or as a named color. For example, red can be specified in three ways:

color: #ff0000
color: rgb(255, 0, 0)
color: red

RGBA colors are equivalent to RGB plus an opacity (or alpha) value between 0 and 1. When the opacity is 0 the color is transparent, and when the opacity is 1 the color is identical to the RGB color. RGBA colors are expressed as an rgba() function.

color: rgba(255, 0, 0, 1)    // red
color: rgba(255, 0, 0, 0.5)  // translucent red
color: rgba(255, 0, 0, 0)    // fully transparent

CMYK

CMYK colors can be specified using the cmyk() or, alternatively, the equivalent device-cmyk() function syntax. An optional fifth value is for the alpha channel, i.e. for opacity.

color: cmyk(1, 0, 0, 0)       // cyan
color: cmyk(0, 1, 1, 0)       // red
color: cmyk(0, 0, 0, 1)       // black
color: cmyk(0, 1, 1, 0, 0.1)  // translucent red

HSL(A)

HSL(A) colors are supported as of Prince 12.1 .

HSL (Hue-Saturation-Lightness) color values can be specified with the hsl() function. HSL takes three values:

  • Hue is a degree on the color wheel (0 or 360 is red, 120 is green, 240 is blue);
  • Saturation is a percentage value, and
  • Lightness is also a percentage.

Just as with RGB values expressed with the rgb() function an alpha channel for opacity can be added with the rgba() function, so also for HSL color values an alpha channel can be expressed with the hsla() function, which adds a fourth value for alpha - when the opacity is 0 the color is transparent, and when the opacity is 1 the color is identical to the HSL color.

The advantage of HSL over RGB is that it is much more intuitive to use and easier to create sets of matching colors (by keeping the same hue and varying the lightness and saturation values).

Spot colors

Prince also supports named spot colors that can be defined with the @prince-color rule. An alternate color must also be specified with the alternate-color property, using any of the valid notations for RGB, HSL or CMYK colors. This will be used in situations where the named color is not available, such as when viewing the generated PDF file on a display. Please note that alternate-color cannot be RGBA, HSLA or CMYKA.

@prince-color MyColor {
    alternate-color: rgb(255,0,0)
}

Spot colors can be used with the prince-color() function with a specified tint value between 0 and 1, which defaults to 1, or alternatively expressed in percentage. They can also enable overprint:

color: prince-color(MyColor)                  // tint 1.0
color: prince-color(MyColor, 0.5)             // tint 0.5
color: prince-color(MyColor, overprint)       // tint 1.0, overprint
color: prince-color(MyColor, 50%, overprint)  // tint 50%, overprint

Another way to enable overprint is by using the prince-overprint() function, which allows to specify a non-transparent color value.

color: prince-overprint(red);
color: prince-overprint(cmyk(0,1,1,0));

Color Management

Introduction

The purpose of color management is to keep the appearance of colors consistent as they are converted between different devices and media. This is e.g. of advantage when preparing a PDF file on a computer screen before sending it to a printer - the desirable result will be to have a print that looks as close as possible to the display on the screen. Perfect equivalence is not possible, also not least because of the difference between a device with reflected light, such as paper, and one with direct light, such as a screen, but color management helps to achieve a close match in perception.

The conversion of color is facilitated by profiling devices; the set of data that characterizes a device or color space, i.e. the color attributes of the device, is kept as an ICC color profile. Color profiles are often embedded in image files to denote the color space of the image. When the color space is not known, color values are essentially arbitrary numbers without a physical interpretation.

The aim of Prince, within a color-managed workflow, is to preserve color information (namely, color profiles) from the input documents and images, through to the PDF output file.

Color Management and PDF Profiles

As described in the PDF Versions and Profiles section, both PDF/A and PDF/X profiles impose restrictions on the features that may be used in a PDF file, including restrictions on color.

PDF/A and PDF/X files have an output intent that defines the intended output color space of the PDF file. In Prince, the output intent color profile is selected using the --pdf-output-intent command-line option, or using the prince-pdf-output-intent property inside a @prince-pdf at-rule. Both take a filename or URL to an ICC profile as its value.

The URL specified with the --pdf-output-intent command-line option or the prince-pdf-output-intent property will be resolved relative to the base URL of the style sheet or document in which the rule is, and needs to point to an existing color profile file.

@prince-pdf {
    prince-pdf-output-intent: url("ISOcoated_v2_eci.icc")
}

For PDF/X, the output intent must be given as it describes the intended printing process. For PDF/A, Prince assumes an sRGB ICC profile if an output intent is not given.

Briefly, the restrictions on color imposed by PDF/X are:

PDF/X-1
  • All color data must be Grayscale, CMYK or named Spot Colors;
  • Transparency is not allowed.
  • All colors must be characterized by the output intent - Prince implicitly performs color conversions.
PDF/X-3
  • Allows other color spaces but colors must be device-independent, or else characterized by the output intent;
  • Transparency is not allowed.
PDF/X-4
  • Allows other color spaces but colors must be device-independent, or else characterized by the output intent;
  • PDF transparency is supported.

PDF/A requires that all colors to be device-independent, or else characterized by the output intent (thus making them device-independent). Transparency is not allowed.

Color Management in Prince

Prince supports RGB, RGBA, HSL, HSLA, CMYK, and named spot colors. For Prince's color handling, please see the Color section.

As CSS defines RGB colors in the sRGB color space, Prince tags those colors with an sRGB ICC profile in the PDF output. See also the section on Rich black and true black below.

CMYK colors specified using the cmyk() function syntax, or equivalent device-cmyk() syntax, represent device-dependent colors, so they will be left as such in the PDF when possible. Device-dependent color is not allowed in PDF/A or PDF/X, so those CMYK colors will be assumed to be either in the output intent color space (if it is CMYK), or else the color space of the fallback CMYK profile. See the command-line option --fallback-cmyk-profile in the PDF Output Options section, or the prince-fallback-cmyk-profile property.

prince input.html
       --pdf-profile=PDF/A-1b
       --pdf-output-intent=sRGB.icc
       --fallback-cmyk-profile=ISOcoated_v2_eci.icc
@prince-pdf {
    prince-pdf-output-intent: url("sRGB.icc");
	prince-fallback-cmyk-profile: url("ISOcoated_v2_eci.icc");
}

Prince preserves the ICC profiles embedded in bitmap images, unless directed not to (see the ignore-icc-profile value of the prince-image-magic property). If an image does not have an embedded ICC profile, the behavior depends on the color model of the image. Untagged RGB images will be assumed to be in the sRGB color space. Untagged CMYK images will, when necessary, be assumed to be either in the output intent color space (if it is CMYK), or else the color space of the fallback CMYK profile. Untagged grayscale images will be left as DeviceGray in the PDF (in PDF/A and PDF/X, it means it is characterized by the output intent color space).

Color conversion

Prince will convert all the colors in a document to a single color space if the --convert-colors command-line option or the prince-pdf-color-conversion property is used. The destination color space is specified with the --pdf-output-intent option (or the prince-pdf-output-intent property), even when not producing PDF/A or PDF/X files.

Prince automatically converts colors to the output intent color space only when producing PDF/X-1a files. Files in any of the other profiles need also the --convert-colors command-line option or the prince-pdf-color-conversion property if colors are to be converted.

Rich black and true black

In printing, "rich black" is a mixture of CMYK ink colors to produce a darker tone than using the black ink alone ("true black").

The property prince-pdf-color-options controls the encoding of CSS RGB values representing black and grays, i.e. RGB colors with equal values of red, green and blue.

When the value use-true-black is used, such an RGB value will be encoded in the DeviceGray color space in the PDF. A CMYK printer should print the gray level using only the black ink. This is the default setting of Prince.

On the other hand, the use-rich-black value instructs Prince to keep all RGB colors as RGB in the PDF. A CMYK printer should print RGB colors using a mixture of all four CMYK inks.

@prince-pdf {
    prince-pdf-color-options: use-rich-black;
}

Color conversion takes into account the use-true-black value when converting CSS RGB values to CMYK. True blacks and grays will be converted to CMYK with only non-zero values in the K channel. Note, however, that this does not affect bitmap images.

Page color space

The property prince-pdf-page-colorspace controls the color space of pages in the PDF file. It affects the compositing of transparent content onto the page by selecting the color space in which compositing is performed. Prince currently defaults to the RGB color space. It may be useful to set this property to avoid converting the colors of transparent content before it is composited onto the page, possibly resulting in distorted colors.

Filters

The filter property provides graphical effects like blurring, saturating or color shifting an element. Filters can be used alone, or combined in any way. However, the order in which filters are applied matters - applying grayscale() after any other filter will result in a gray result.

In this section we shall examine the various possibilities offered by this property.

The following filters can be used alone, or in any number and combination. Care is to be taken to the order the filters are being applied.

filter: grayscale([ <number> | <percent> ])

This filter converts the input to grayscale. The amount value defines the proportion of the conversion.

filter: sepia([ <number> | <percent> ])

This filter converts the input to sepia. The amount value defines the proportion of the conversion.

filter: saturate([ <number> | <percent> ])

This filter saturates the input. The amount value defines the proportion of the conversion.

filter: hue-rotate(<angle>)

This filter applies a hue rotation to the input. The angle value defines the number of degrees around the color circle that the rotation will be performed.

filter: invert([ <number> | <percent> ])

This filter inverts the samples of the input. The amount value defines the proportion of the conversion.

filter: opacity([ <number> | <percent> ])

This filter applies transparency to the input. The amount value defines the proportion of the conversion. This function is similar to the opacity property.

filter: brightness([ <number> | <percent> ])

This filter makes the input appear more or less bright. The amount value defines the proportion of the conversion. Values over 100% are allowed.

filter: contrast([ <number> | <percent> ])

This filter controls the level of contrast. The amount value defines the proportion of the conversion.

filter: blur(<length>)

This filter applies a gaussian blur to the input. The amount value defines the proportion of the conversion.

filter: drop-shadow(<length>{2,3} <color>?)

This filter applies a drop shadow effect to the input. This is a blurred, offset version of the input, composited below the image.

Alternatively, a filter can be written in SVG and can be referenced by a URL:

filter: url(<url>)
This filter takes the URL of an SVG filter. An anchor can be used to reference a specific filter element.

The resolution used when rasterizing to images for applying CSS and SVG filters is controlled through the prince-filter-resolution property. The default value is 96dpi for compatibility with web browsers.

Images

Prince supports JPEG, PNG, TIFF and GIF images as well as Scalable Vector Graphics (SVG).

Images can be included in XHTML and DocBook documents using the appropriate image elements, which are pre-defined in the default style sheets.

Images can also be included in arbitrary XML documents using the CSS content property, which can be used to specify the image filename.

Furthermore, images are widely used in style sheets for the background. CSS allows also for several mechanisms to manipulate images and background images.

Please note that Prince tries to preserve the ICC color profile embedded in images - for details see the Color Management section.

Images in XHTML

The img element is used to include images in XHTML documents.

XML

<img src="picture.jpg" alt="A Nice Picture"/>

Images in DocBook

The imagedata element is used to include images in DocBook documents.

XML

<mediaobject>
    <imageobject>
      <imagedata fileref="picture.jpg"/>
    </imageobject>
</mediaobject>

Images in Arbitrary XML

Images can be included in arbitrary XML documents by using the CSS content property to specify the image filename.

The content property can specify the image filename directly, or it can take the filename from an attribute of the element to which it has been applied.

CSS

picture { content: url("picture.png") }

XML

<para> A nice <picture /> here. </para>

The content property directly specifies the filename of the image that will be used as the content of the picture element.

CSS

picture { content: attr("src", url) }

XML

<para> A nice <picture src="picture.tiff" /> here. </para>

The content property specifies that the content of the picture element will be an image loaded from the filename specified by the src attribute of the element.

CSS and Images

Images can be added to a document as content or decoration, and can be modified with the help of CSS properties.

Background Images

Several properties are available to add background images: background-image is used to add an image to a page, while background-position, background-attachment and background-repeat are used to position it precisely, also defining its appearance. See also Background.

Images can also be added to style a list with the property list-style-image (see also List marker style).

Image Orientation

Usually images have the correct orientation when included in a document. However, it can be important to honor the orientation field in the EXIF data of JPEG and TIFF images, which can be done with the image-orientation property.

The property applies only to content images (e.g. replaced elements and generated content), not decorative images (such as background-image).

Image Size

CSS properties also control the size of images in print. Unless an explicit size for an image is specified by using the width and height properties, Prince will determine the intrinsic size from the image resolution (DPI), which can be overridden using the prince-image-resolution property:

prince-image-resolution: 300dpi;        /* set an explicit DPI */
prince-image-resolution: normal;        /* 1 image pixel maps to 1px unit */
prince-image-resolution: auto, normal;  /* auto-detect, fallback to normal */
prince-image-resolution: auto, 96dpi;   /* auto-detect, fallback to 96dpi */

Not all images have an internal resolution set, so sometimes it is necessary to specify an explicit resolution. Alternatively, specifying a resolution of normal means that an image that is 100 pixels wide, will be the same size on the page as a block that is 100px units wide.

The property prince-background-image-resolution does the same for background images.

Please note that specifying prince-image-resolution and prince-background-image-resolution only affects the default DPI of images, ie. it makes them physically bigger or smaller on the page - it does not affect the number of pixels in the image, and thus the PDF file size will be the same.

To reduce the PDF file size, JPEG images can be recompressed at a lower quality level, or PNG images be converted to JPEG, with the prince-image-magic property. See also Image Magic.

Scalable Vector Graphics (SVG)

SVG can be included in any XML document simply by adding a svg element.

Global definitions of graphical elements are supported, for example references to elements outside of the current SVG fragment, either in the same document or other documents. Defining these elements in a <defs> element helps understandability of the SVG element. You can use a <use> element to reference those elements later.

The display, float, and flow properties and all margin, padding, border, and background properties can be applied to the top-level svg element but not to child elements within it.

The following elements are supported inside the svg element:

g for grouping related graphics elements
rect for drawing rectangles
circle for drawing circles
ellipse for drawing ellipses
line for drawing lines
mask for masking another element
polyline for drawing polylines
polygon for drawing polygons
path for drawing arbitrary paths
text for drawing text
tspan for adjusting text and font properties inside the text element
image for including bitmap image files
a for creating hyperlinks
defs for containing referenced elements
use for using a referenced element

Viewbox and viewport

The svg element should include view box and view port information so that the SVG content can be correctly mapped to the containing box.

Attributes
width the width of the viewport (100% of the container width, if omitted)
height the height of the viewport (100% of the container width, if omitted)
viewBox(x y width height) the x, y coordinate of the top left corner of the viewbox and the width and height of the viewbox

XML

<svg width="3cm" height="2cm" viewBox="0 0 300 200">
    <!-- the SVG content -->
</svg>

Rectangles

Rectangles are created using the rect element.

Attributes
x, y the x, y coordinates of the top left corner of the rectangle
width the width of the rectangle
height the height of the rectangle
rx, ry the radii for rounded corners

XML

<svg viewBox="0 0 500 300"
        width="10cm" height="6cm">
 <g fill="none" stroke="gray" stroke-width="20">
  <rect x="50" y="50" width="400" height="200"
        rx="80" ry="50"/>
 </g>
</svg>

Output

Rect example

Circles

Circles are created using the circle element.

Attributes
cx, cy the centre of the circle
r the radius of the circle

XML

<svg viewBox="0 0 200 200"
        width="5cm" height="5cm">
 <g fill="none" stroke="gray" stroke-width="20">
   <circle cx="100" cy="100" r="100"/>
 </g>
</svg>

Output

Circle example

Ellipses

Ellipses are created using the ellipse element.

Attributes
cx, cy the centre of the ellipse
rx, ry the radii of the ellipse

XML

<svg viewBox="-10 0 220 200"
        width="6cm" height="6cm">
 <g fill="none" stroke="gray" stroke-width="20">
  <ellipse cx="100" cy="100" rx="100" ry="60" />
 </g>
</svg>

Output

Ellipse example

Lines

Lines are created using the line element.

Attributes
x1, y1 the start point of the line
x2, y2 the end point of the line

XML

<svg viewBox="0 0 100 50"
        width="6cm" height="3cm">
 <g stroke="gray" stroke-width="2">
    <line x1="10" y1="25" x2="90" y2="25"/>
 </g>
</svg>

Output

Line example

Masks

Masks are created using the mask element.

Attributes
x the x-axis coordinate of one corner of the rectangle
y the y-axis coordinate of one corner of the rectangle
width the width of the rectangle
height the height of the rectangle

XML

<svg xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient id="Gradient">
      <stop offset="0" stop-color="white" stop-opacity="0" />
      <stop offset="1" stop-color="white" stop-opacity="1" />
    </linearGradient>
    <mask id="Mask" x="0" y="0" width="200" height="200">
      <rect x="0" y="0" width="200" height="200" fill="url(#Gradient)"  />
    </mask>
  </defs>

  <rect x="0" y="0" width="200" height="200" fill="green" />
  <rect x="0" y="0" width="200" height="200" fill="red" mask="url(#Mask)" />
</svg>

Output

Mask example

Polylines

Polylines are created using the polyline element.

Attributes
points list of points that defines the line. Points are separated by whitespace and each point is a pair of x, y coordinates separated by comma.

XML

<svg viewBox="0 0 600 400"
        width="6cm" height="4cm">
 <g stroke="gray" stroke-width="10">
  <polyline points="50,300 200,300 200,100
               400,100 400,300 550,300" />
 </g>
</svg>

Output

Polyline example

Polygons

Polygons are created using the polygon element.

Attributes
points list of points that defines the line. Points are separated by whitespace and each point is a pair of x, y coordinates separated by comma.

XML

<svg viewBox="600 0 600 400"
        width="6cm" height="4cm">
 <g fill="none" stroke="gray" stroke-width="10">
    <polygon points="850,75  958,137.5 958,262.5
                    850,325 742,262.6 742,137.5" />
 </g>
</svg>

Output

Polygon example

Paths

The path element is for drawing arbitrary paths. The d attribute inside the element path takes a list of path commands. Parameters of a command can be separated either by whitespace or a comma.

Command Parameters Meaning
M (absolute), m (relative) (x y)+ moves to the given (x, y) coordinates to start a new subpath
Z or z none closes the current subpath
L (absolute), l (relative) (x y)+ draws a line to the given (x, y) coordinates
H (absolute), h (relative) x+ draws a horizontal line to the given x coordinates
V (absolute), v (relative) y+ draws a vertical line to the given y coordinates
C (absolute), c (relative) (x1 y1 x2 y2 x y)+ draws a cubic Bézier curve to the given (x,y) coordinates, uses the given (x1,y1) coordinates as the first control point, the (x2,y2) coordinates as the second control point
S (absolute), s (relative) (x2 y2 x y)+ short hand of the C/c command: the reflection relative to the current point of the second control point of the previous command is used as the first control point.
Q (absolute), q (relative) (x1 y1 x y)+ draws a quadratic cubic Bézier curve to the given (x,y) coordinates, uses the given (x1,y1) coordinates as the control point.
T (absolute), t (relative) (x y)+ short hand of the Q/q command: the reflection relative to the current point of the control point of the previous command is used as the control point.
A (absolute), a (relative) (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ draws an elliptical arc to (x, y): the size and rotation of the ellipse are defined by two radii (rx, ry) and the x-axis-rotation; the center (cx, cy) of the ellipse is also determined by the large-arc-flag and sweep-flag constraint.

XML

<svg viewBox="0 0 600 400"
        width="12cm" height="8cm">
 <g fill="none" stroke="red" stroke-width="10">
    <path d="M100,200 C100,100 250,100
		    250,200 S400,300 400,200" />
 </g>
</svg>

Output

Path example

Text

The text element is for writing arbitrary text. The tspan element is supported inside the text element, for adjusting text position and font properties.

Attributes
x, y the absolute position of the text
dx, dy the relative offset of the current text position (optional)

XML

<svg viewBox="0 0 1000 300"
        width="10cm" height="3cm">
    <text x="200" y="150" fill="blue" font-size="70">
      That
        <tspan dx="2em" dy="-50" font-weight="bold" fill="red" >
          is
        </tspan>
        <tspan dy="100">
           a peach!
        </tspan>
    </text>
</svg>

Output

Text example

Images

The image element is for including external image files, either bitmap images or other SVG images.

Attributes
xlink:href the URL of the image to include
x, y the x, y coordinates of the top left corner of the image
width the width of the image
height the height of the image

Note that the href element must be placed in the XLink namespace: http://www.w3.org/1999/xlink in order to work.

XML

<svg xmlns:xlink="http://www.w3.org/1999/xlink"
    ...
    <image x="100" y="100" width="50" height="50" xlink:href="myimage.jpg"/>
    ...
</svg>

Links

The a element is for creating hyperlinks.

Attributes
xlink:href the URL of the link

Note that the href element must be placed in the XLink namespace: http://www.w3.org/1999/xlink in order to work.

XML

<svg xmlns:xlink="http://www.w3.org/1999/xlink"
    ...
    <a xlink:href="http://www.example.com">
        ...
    </a>
    ...
</svg>

Transformations

The transform attribute can be used on g, path, and all of the basic shape elements. It accepts any sequence of the following transformations separated by whitespace.

  • translate(tx ty)
  • scale(sx [sy])
  • rotate(angle)
  • skewX(angle)
  • skewY(angle)
  • matrix(a b c d e f)

XML

<svg viewBox="-150 -200 1400 700" width="12cm" height="6cm">
  <g fill="none" stroke-width="30">
    <rect width="400" height="200" stroke="lightgray"/>
    <rect width="400" height="200" stroke="darkgreen" transform="rotate(-30)"/>
    <g transform="translate(700 100) rotate(-30)">
      <rect width="400" height="200" stroke="blue"/>
    </g>
  </g>
</svg>

Output

Transform example

Style Properties

The following style properties are supported on SVG elements:

  • baseline-shift
  • clip-path
  • clip-rule
  • dominant-baseline
  • font-family
  • font-size
  • font-style
  • font-weight
  • fill
  • fill-opacity
  • fill-rule
  • marker-start
  • marker-mid
  • marker-end
  • stop-color
  • stop-opacity
  • stroke
  • stroke-dasharray
  • stroke-dashoffset
  • stroke-linecap
  • stroke-linejoin
  • stroke-miterlimit
  • stroke-opacity
  • stroke-width
  • text-anchor

Style properties can be applied using SVG presentation attributes:

<rect fill="yellow" stroke="blue" stroke-width="20"
        width="200" height="100"/>

Or by using CSS properties inside the style attribute or element:

<rect style="fill:yellow; stroke:blue; stroke-width:20"
        width="200" height="100"/>

Alternatively, style properties can be applied by linking a stylesheet, or an XML stylesheet:

SVG

...
<?xml-stylesheet type="text/css" href="style.css"?>
...
<rect width="200" height="100"/>

CSS

svg rect {
    fill: yellow;
    stroke: blue;
    stroke-width: 20;
}

Rasterization

Prince allows for the output of a rasterized image rather than, or in addition to a PDF output. This produces a JPEG or PNG image of the content, which can be convenient when e.g. planning to use it as a quick preview or thumbnail of the PDF content to display on a website, as can e.g. be seen in the Sample Documents section on this website.

Rasterization is enabled with the --raster-output command-line option, which also defines the template of the file naming. The output format can be chosen either based on the extension of the file name, or by explicitly indicating it.

  prince doc.html --raster-output=page_%02d.png

Furthermore the range of pages to rasterize and the resolution of the raster output can be tweaked in order to determine the number of pages in rasterized format, and the size of the images.

  prince doc.html --raster-output=title-thumbnail.jpg --raster-pages=first --raster-dpi=24

If you want to rasterize the HTML to an image format that supports transparency (PNG, not JPEG) and have a transparent background, in order to composite it with something else later, the command-line option --raster-background can be used with the value transparent.

A full list of rasterization possibilities can be found in the Raster Output Options section.

Prince Tips and Tricks

…aka the Prince Cookbook, collects recipes to achieve certain common or complex tasks useful when preparing a document for printing. Each recipe shows the required features in a "You need" ingredients list and provides a step-by-step explanation to guide you to the required goal.

Table of Contents

You need
JavaScript in Printed Media
The "Two-Pass" Solution
Generated Content Functions
  • content: target-counter()
  • content: leader()

Prince offers several properties and functions to facilitate the creation of a Table of Contents.

Typically, a table of contents is generated for a document by collecting the headings of each chapter, each one provided with an id attribute, into a list or, if necessary, also into nested lists, by means of JavaScript or in some other way, in order to generate a navigation menu for the document.

Each list item contains a hyperlink to the heading's id. This list functions as a navigation menu when the document is viewed in a browser.

The transformation into a proper table of contents happens with CSS when Prince generates the PDF - the resulting document will be paged, and possibly be intended for printing. It means that the hyperlinks need to be integrated with an indication of the correct page on which the target is located.

This is achieved automatically with the target-counter() function in the content property, using the page counter. The URL is being automatically fetched from the href attribute of the hyperlink element <a>.

#toc a:after {
  content: target-counter(attr(href), page);
}

The page numbers are best styled right-aligned, while the link texts are left-aligned. An easy way to achieve this is with the leader() function: it defines a literal string, which expands to fill the available space on the line like justified text, by repeating the string as many times as necessary. The complete CSS entry for a simple table of contents entry thus looks like this:

#toc a:after {
  content: leader('.') target-counter(attr(href), page);
}

Simple Table of Contents

Our example document generates at Table of Contents (TOC) by way of JavaScript. You can easily test it by running Prince from the command line:

$ prince --javascript http://css4.pub/2018/toc -o toc.pdf

A second example document generates at ToC by way of JavaScript and, even more impressively, the script also prints out an index which is added to the end of the document, to be used when running Prince a second time (see The "Two-Pass" Solution). Notice how subsequent page numbers in the index are folded into a range. To produce this document, try running these commands from a Linux command-line:

$ wget http://css4.pub/2017/musick/musick.html -o foo.html;
$ prince --javascript foo.html >>foo.html;
$ prince --javascript foo.html -o musick.pdf;

You can view the resulting PDF here.

Multifile Table of Contents

For longer books, it makes sense to split chapters into separate files. Generating a Table of Contents across all files is tricky in JavaScript since scripts only see one file at a time. In Prince, you can work around this limitation with a two-pass solution (see The "Two-Pass" Solution) where the first pass collects items for the ToC, and the second pass generates the PDF with the ToC.

To try this for yourself, first fetch these five sample files into your own file system, e.g. by running:

$ wget http://css4.pub/2018/multifile-toc/toc.js;
$ wget http://css4.pub/2018/multifile-toc/toc.html;
$ wget http://css4.pub/2018/multifile-toc/ch1.html;
$ wget http://css4.pub/2018/multifile-toc/ch2.html;
$ wget http://css4.pub/2018/multifile-toc/style.css;

Then, run Prince twice:

$ prince --javascript --script=toc.js ch1.html ch2.html -o book.pdf >> toc.html;
$ prince toc.html ch1.html ch2.html -o book.pdf;

You can view the resulting PDF here.

Thinking in Spreads

You need
Paged Media
  • Selecting pages
  • Controlling pagination
Box Model
Prince extensions to floats
Paragraph formatting

Prince produces PDFs - which are a prominent example of paged media. The main difference with conventional CSS design for browsers is to always keep in mind that you are dealing with pagination, i.e. the content is placed on discrete pages.

The basic unit for paged media in print is the page, organized in page spreads: the left page, called verso in a left-to-right script (see Writing Mode), and the right page, called recto, are of the same size and typically are symmetrical to each other and are centered on the gutter. Selected and Named pages can be placed recto or verso, and Prince expands several properties and the @page at-rule pseudo-classes with the values verso and recto, or inside and outside, referring to the layout on each page of the spread to facilitate the work with page spreads.

Pagination on a page spread

You have control on wether to place specific selected and named pages right or left, or recto or verso with the help of break-before and break-after, each of which takes the values recto and verso in addition to the traditional values.

h1 {
    break-before: recto;
}

This rule places an h1 element always at the beginning of a recto page.

Pages can also be specifically targeted and styled with the @page at-rule pseudo-classes :right and :left, or :recto and :verso.

Layout on a page spread

Using the values right and left when placing elements on pages symmetrically arranged around the central gutter is possible, but rather cumbersome, since their placement depends on the placement of the page on a spread. Prince offers the extensions inside and outside to ease the task.

p {
    margin: 2em;
}
@page:left {
    margin-right: 3em;
}
@page:right {
    margin-left: 3em;
}

This example creates a bigger margin around the central gutter.

So, when you start thinking about the layout box model, Prince offers the properties margin-inside and margin-outside to help styling.

p { 
    margin: 2em;
    margin-inside: 3em;
}

This example creates a bigger margin around the central gutter, like the previous one - albeit in a shorter way.

Floats are particularly sensitive to the placement on the page with regards to whether it is a left-facing or right-facing page. Prince extends the float property (and the property clear) with the values inside and outside. For details please see the chapter Floats.

On a paragraph level, the properties text-align and text-align-last similarly take the keywords inside and outside to help achieving a smooth layout.

@page:verso {
    @top-left { content: counter(page) }
    @top-right { content: string(book-title) }
}
@page:recto {
    @top-left { content: string(chapter-title) }
    @top-right { content: counter(page) }
}
h1 {
    text-align: center;
    string-set: book-title content();
}
h2 {
    text-align: outside;
    string-set: chapter-title content();
}
img {
    float: inside;
}

This style snippet could be part of the stylesheet for a little booklet - it displays the page number in the upper outside corners, the book title in the upper inside of the left, or verso page, and the chapter title in the upper inside of the right, or recto page. Chapter headings are aligned to the outside of the page spreads, while any image in the book is floated close to the central gutter.

Long Tables

You need
Tables
  • Running table headers and footers
  • Table captions

One of the main differences when designing for paged media is that you need to think about concrete pages, as opposed to a continuous flow of the page designed for the web and for web browsers. A problem may arise when elements such as tables are longer than the page they need to be displayed on.

The table itself is naturally split over several pages - but if you want table headers and footers repeated on each page, you need to code them in the HTML of the document by using the elements thead and/or tfoot. The content of these elements will be carried on to all the subsequent pages on which the table appears.

Tables can also be provided with a table caption by using the caption HTML element, or by styling an arbitrary element with display: table-caption to be made to behave like caption elements. The caption is positioned above the table by default, but it can be moved to the bottom with the caption-side property.

When a table spans across more than one page, the prince-caption-page property determines whether table captions will be displayed on the first page of a table, or only on the following pages, or repeated on every page that a table appears on. See also Fancy Table Captions.

table + p {
    display: table-caption;
    caption-side: bottom;
    prince-caption-page: following;
}

Fancy Table Captions

You need
Tables
  • Table captions
Long Tables

HTML tables only have one caption per table. However, in printed form a table might span several pages (see Long Tables) and it might be desirable to have separate captions for the first and the following pages - you might want to add "cont." to the caption of the first one, or otherwise differentiate them. Prince offers an extension mechanism to do so.

As mentioned in Long Tables, when a table spans across more than one page, the prince-caption-page property determines whether table captions will be displayed on the first page of a table, or only on the following pages, or repeated on every page that a table appears on. This opens up the possibility to have a different caption on the first and on the following pages.

You might define a caption in HTML for the main table caption - to be displayed on the first page. Additionally, you make another element into a table caption with the display property - and display it only on the following pages!

The paragraph functioning as a table caption can be hidden in browsers by using CSS Media Queries.

HTML

<table>
  <caption>Demo table</caption>
  <tr>
    <td>A</td>
    <td>B</td>
  </tr>
  <tr>
    <td>C</td>
    <td>D</td>
  </tr>
  <tr>
    <td>E</td>
    <td>F</td>
  </tr>
</table>
<p>Demo table (cont.)</p>

CSS

caption {
    caption-side: bottom;
    prince-caption-page: first;
}
table + p {
    display: table-caption;
    caption-side: bottom;
    prince-caption-page: following;
}

Page Headers and Footers

You need
Page regions
Generated Content

When preparing a document for print, "running" headers and footers repeating on every page, such as page numbering and titles of the book and of the current chapter, are a common need.

Prince uses CSS for these headers and footers and for styling them.

Each page is structured in Page regions - most page content is located inside the page area, including the Footnotes, but the page-margin boxes contain most of the content repeating in slightly varied way across the whole book - the running headers and footers.

A typical case is page numbering, which can easily be obtained with Generated Content: the current page number can be printed in a page region with the content property. (See also Page Numbering).

@page {
    @bottom {
        content: counter(page)
    }
}

By using Named pages, you can style the page numbering of the Preface with roman numbers and the main pages with arabic numbers - see the example Restarting page numbering.

The title of the book, or the current chapter, can be copyied into the page regions by using the string-set property. For details, please see the Copying content from the document chapter.

CSS

@page {
    @top { content: string(doctitle) }
}

h1 { string-set: doctitle content() }

The @page rule specifies that the top-center page region will contain the text content of the document title copied from the text content of the h1 element in the document.

If some special formatting of the text in the margin box is required, copying the text will not suffice - you need to remove an element from the natural page flow to place it in the margin box. See Taking elements from the document for details.

Dictionary Page Headers

You need
Page regions
Generated Content
The optional page-policy value
  • content: string(term, first)
  • content: string(term, last)

A peculiar and interesting use of page headers happens in dictionaries: typically, you might want to display page headers like "a-af", where "a" is the first definition on the page and "af" is the last one. This can easily be obtained by adding The optional page-policy value to the string() function.

The string-set property is applied to each definition in the dictionary (the b:first-child from the following example), and then the first and last page policy values are use to select the relevant definition to display in the page header.

@page {
  @top-left { content: string(term, first);}
  @top-right { content: string(term, last);}
}

.chapter p b:first-child { string-set: term content() }  /* pick up term to be used in running header */

This is the crucial set of rules for the Dictionary sample.

The dictionary sample is furthermore noticeable for its use of the optional page policy keyword first-except: the current letter of the alphabet is displayed on each page heading, except for the page on which the letter appears in the body of the page, starting the new section.

@page {
  @top-center { content: string(letter, first-except);}
}

.chapter header { string-set: letter content() }

Page Numbering

You need
Paged Media
  • Selecting pages
Generated Content
  • Counters and Numbering
    • content: counter(page)

Paged media is organized in pages - and numbering the pages is a common task: generated content does this for you automatically. The easiest way of doing so is numbering them sequentially from the first to the last page.

To use a counter, it usually first needs to be initialized with the counter-reset property, which can be applied to any element and initializes one or more counters to the specified values, or to zero if no value is specified. Once initialized, the counter will be displayed with the counter() function in the content property.

Page counters work a bit more simple and usually don't need to be explicitly initialized or incremented.

@page {
  @bottom {
    content: counter(page);
  }
}

However, if you want to restart the numbering after the Preface of your book, you need to name the pages (see Named pages) and the counter needs to be re-initialized with the main content. See also the example Restarting page numbering.

.preface {
  page: preface;
  counter-reset: page 1;
}
@page preface {
  @bottom {
    content: counter(page, lower-roman);
  }
}

.main {
  page: main;
  counter-reset: page 1;
}
@page main {
  @bottom {
    content: counter(page);
  }
}

The page numbers can be referenced with the target-counter() function. This provides a convenient mechanism when you want to print out a page reference that on an interactive medium, such as can be seen in a web browser, might be expressed with a hyperlink.

CSS

a[href]::after {
    content: " [See page " target-counter(attr(href), page) "]";
}

This will add a cross-reference after every link with the correct page number determined automatically. For example: [See page 17].

If you are referencing the pages in the Preface, marked with lower roman-style numbers, you need to re-specify the counter style for the target counter - the style is not automatically taken over.

CSS

a[href|="#preface"]::after {
    content: " [See page " target-counter(attr(href), page, lower-roman) "]";
}

In some documents, particularly those that are unbound such as office documents, it can be useful to show the total number of pages on each page. The total number of pages can be accessed by using the pages counter. This is a pre-defined counter that is fixed to the total number of pages in the document.

@page {
  @bottom {
    content: "Page " counter(page) " of " counter(pages);
  }
}

This rule will generate page footers such as "Page 1 of 89".

Footnotes per Column

You need
Columns
Page and column floats
Footnotes
  • float: prince-column-footnote

Prince has a simple way of creating footnotes: the @footnote page area, where footnotes can be floated to with the float property. For details see Footnotes.

In a multi-column layout (see Columns), footnotes can be placed at the bottom of the page, spanning all columns. But usually you want to position the footnote at the bottom of the column the footnote call appears in.

To achieve this, the values prince-column-footnote or prince-column-inline-footnote of the float property are used.

The value prince-column-footnote transforms the element into a column footnote: it creates a footnote call in the place where it appears in its natural flow, and moves the element to the bottom of the column. The footnote marker is placed outside of the block of the footnote. With the value prince-column-inline-footnote, the footnote marker is placed inside of the block of the footnote.

float: prince-column-footnote

Multiple Footnotes

You need
Prince extensions to floats
Footnotes
  • float: footnote
Generated Content Functions
Using target-counter()

In some cases it might happen that you want to point several footnote calls at the same footnote. Prince offers a convenient mechanism to achieve this by combining regular footnotes with the generated content function target-counter().

First we create our regular footnotes - the only extra step we need to do, is to provide each footnote with a unique ID.

<p>
This paragraph has a footnote.<span class="fn" id="fn1">First footnote.</span>
</p>

When another foonote call needs to be pointing at this, already existing footnote, we have to create it manually by adding a link to this footnote's ID.

<p>
This paragraph refers to the first footnote.<a class="rfn" href="#fn1"></a>
</p>

This footnote call will be created by using the generated content function target-counter() referencing the footnote counter.

content: target-counter(attr(href), footnote);

When creating regular footnotes, Prince automatically takes care of the styling of the footnote calls, but the manually created ones need to be explicitly styled. The following are the default rules that style a footnote call - here shown with all the rules necessary for creating all the footnote calls:

.fn {
    float: footnote;
}

.rfn {
    color: inherit;
    text-decoration: none;
    content: target-counter(attr(href), footnote);
    vertical-align: super;
    line-height: none;
    font-size: 83%;
}

Sidenotes

You need
Prince extensions to floats
Footnotes
  • float: footnote
Styling and behavior of footnotes

Prince has a simple way of creating footnotes: the @footnote page area, where footnotes can be floated to with the float property. For details see Footnotes.

It gets slightly more complicated when you want to position the footnotes not under the text, in their default position, but at the side of the pages as sidenotes. Two approaches are possible, each with its advantages and drawbacks. Either

  • the footnote area is positioned to the side of the page (see also Styling and behavior of footnotes), or
  • the sidenotes are floated not to the footnote area, but simply to the left or right side of the page.

We shall see each approach separately.

Positioning the footnote area

A straightforward approach for sidenotes is to position the footnote area to the desired place, instead of leaving it in its default position.

@page {
    @footnote {
        position: absolute;
        left: -90px;
        width: 60px;
    }
}

This rule moves the footnotes area to the left side of a page.

The advantage of this approach is that footnote calls and markers are created automatically (see Footnote calls and Footnote markers).

The biggest disadvantage is that the footnotes are not placed to the side of the location of the footnote calls, but are inserted into the footnote page area filling the space from the top of the page. Should this be of importance, use the second approach instead.

Floating the footnote left or right

The footnote text is floated to the left (or right) and moved out of the way with negative margins.

.footnote {
  float: left;
  max-width: 60px;
  margin-left: -90px;
}

This rule floats the footnotes to the left side of a page.

The advantage is to position the footnotes vertically aligned with the footnote calls.

The disadvantage is that footnote calls and markers are not created automatically, but need to be manually added as counters, and styled. Also, footnotes may overlap vertically if they are too close together.

A variant of this approach, useful when creating floating sidenotes in a multicol layout, can make use of some scripting to determine, with the help of The Box Tracking API, in which column the sidenote call, and thus the sidenote, is placed - making sure the sidenote is always in the correct position. You can see this in full action in the Sidenotes sample (HTML - PDF).

Endnotes

You need
Scripting

Endnotes are quite easy as their placement is not relative to the page. There are two ways of creating them.

In their most simple form, an endnote is placed at the end of the document by the author, with a (hyperlinked) call in the text.

However, it can be laborious to manually synchronize references in this manner. A more convenient alternative is to keep the notes inline and to move them to the end of the document at the time of formatting. This is a simple tree transformation which can be performed by a script. The following sample document features references which are kept inline and moved to the end by a script:

  • HTML document
  • PDF document

No special CSS formatting is required to support endnotes.

In a similar fashion table notes can be created. These are a variation of endnotes. However, instead of moving the notes to the end of the document, the notes are moved to the end of the table, or to the end of the table cell. Again, this is a simple tree transformation which doesn't require anything special from CSS.

The table in the above document sample also has inline notes that are moved to the end of the table by a script.

Hyperlinks in Print

You need
Generated Content
Generated Content Functions
Cross-references
  • Using target-counter()
  • Using target-content()

Hyperlinks are a direct reference to another location, easy to follow on the interactive web page, or a PDF loaded in a viewer, by clicking on it. On the printed page, this mechanism obviously does not work.

Prince offers some CSS functions to help translating hyperlinks into print-friendly display, useful in different scenarios: target-counter(), target-content() and attr(), to be used with the content property. (See also Generated Content Functions).

The target-counter() function can be used to reference the value of a counter at a linked element, and it can specify any counter, allowing cross-references to refer to list items, chapters or sections as well as pages.

Used with generated content after a hyperlink, it will add a cross-reference with the correct page number determined automatically.

CSS

a[href]::after {
    content: " [See page " target-counter(attr(href), page) "]"
}

This adds something like "[See page 17]" after each link. Note the use of the function attr() inside the target-counter() function.

It can also take an optional counter style, similar to the normal counter() function.

CSS

a[href]::after {
    content: " [See chapter "
             target-counter(attr(href), chapter, upper-roman)
             "]"
}

This will add a cross-reference after every link with the correct chapter number determined automatically and displayed using roman numerals. For example: "[See chapter IV]".

The target-content() function can be used to reference the text content of the linked element.

CSS

a[href]::after {
    content: " [See '" target-content(attr(href)) "']"
}

This will add a cross-reference after every link that includes the text of the element being linked to, such as a chapter title. For example: "[See 'Introduction']".

The attr() function, used in the previous examples inside the other functions, can also be used on its own to insert the URL of a remote resource.

CSS

a[href]::after {
    content: " [Located at '" attr(href) "']";
}

This will add the URL after every link. For example: "[Located at 'http://www.princexml.com/']".

Image Magic

You need
Images
CSS and Images
  • prince-image-magic

The prince-image-magic property performs various image-related, Prince-specific tasks that do not fit into other existing CSS properties. It applies magic to images!

To reduce the PDF file size, JPEG images can be recompressed at a lower quality level by using the function recompress-jpeg(quality%) with the required quality percentage as argument.

PNG images can be converted to JPEG images with the keyword convert-to-jpeg (using the default compression rate), or they can also be converted to JPEG with the required compression rate as argument with the function convert-to-jpeg(quality%).

Prince usually strips unnecessary metadata from JPEG images to help contain size. But it might happen that you need that extra data, possibly for further downstream processing. The keyword jpeg-verbatim inhibtis this stripping and includes the images without modification in the PDF file.

Two more keywords perform more obscure tasks that might be required in very specific circumstances: the keyword ignore-icc-profile causes Prince to ignore any ICC color profile embedded in the image, useful e.g. in those cases when the embedded ICC profile is broken; and snap-to-integer-coords can be used to avoid blurring of images in some PDF viewers.

Several of the values can be combined, to perform more than one magic on images - for details please check the grammar of the prince-image-magic property.

img {
    prince-image-magic: recompress-jpeg(50%) convert-to-jpeg(50%) snap-to-integer-coords;
}

This example recompresses all JPEG images to 50%, converts any non-JPEG images to JPEG with the same quality, and snaps them all to integer coordinates to avoid blurring in some PDF viewers.

Hyphenation

You need
hyphens
  • prince-hyphenate-character
  • prince-hyphenate-before
  • prince-hyphenate-after
  • prince-hyphenate-limit-lines
  • prince-hyphenate-patterns

The property hyphens controls whether hyphenation is allowed to create opportunities to wrap within a line of text.

The default value of the hyphens property is manual - to enable automatic hyphenation in a body of text, the value auto has to be declared.

The value none instructs never to hyphenate, while the default value manual tells Prince to only hyphenate when there are characters inside the word that explicitly suggest hyphenation opportunities, such as e.g. "soft hyphens" (represented either by the Unicode character U+00AD or the HTML entity &shy;). With the value auto, words may be broken at appropriate hyphenation points as determined automatically by the language-appropriate hyphenation resources, or by hyphenation characters in a word.

In order to make automatic hyphenation work as intended, it is important to communicate to Prince the natural language the text is in, so that the language-specific hyphenation rules can be applied - this is done by means to the lang or xml:lang attributes.

The character shown at the end of a line when the word is hyphenated can be specified with the prince-hyphenate-character property.

Fine-tuning of hyphenation can be done with the prince-hyphenate-after and prince-hyphenate-before properties to determine the minimum number of letters in a word that may be moved to the next line or that may be left at the end of a line when the word is hyphenated.

The prince-hyphenate-limit-lines property is used to determine the maximum number of consecutive lines that may end with a hyphenated word.

Prince uses the hyphenation patterns from the CTAN archive - the full archive is accessible here. The default hyphenation patterns can be found in the installed hyph.css file, located in the default style sheets location (see Installation Layout).

Hyphenation patterns for the following languages are provided:

da Danish
de German
en-US English
es Spanish
fi Finnish
fr French
is Icelandic
it Italian
lt Lithuanian
pl Polish
pt Portuguese
ru Russian
sl Slovenian
sv Swedish

A special case is Thai hyphenation, supported thanks to the LibThai package.

To add hyphenation patterns for other languages, download them from the CTAN archive. Save the files for the chosen language without the .txt extension, and link to the pattern file (with the .pat extension) with the prince-hyphenate-patterns CSS property. Prince determines which language to use for hyphenation with the help of the :lang() CSS selector, which in turn checks the lang or xml:lang attributes of the document:

:lang(en-GB) {
    prince-hyphenate-patterns: url("hyph-en-gb.pat");
}
<span lang="en-GB">supercalifragilisticexpialidocious</span>

Prince only supports local hyphenation dictionaries.

Typographic Ligatures

You need
OpenType Features in Prince
font-variant: prince-opentype()
prince-text-replace

Prince supports typographic ligatures found in OpenType fonts, i.e. Prince will replace certain characters that appear next to each other with other special glyphs that join those two characters together into one single glyph.

A prominent example of a typographic ligature is fi, which replaces the two characters fi with a single glyph.

Prince automatically enables ligatures declared by the OpenType fonts with the liga feature (see OpenType Features in Prince). This feature covers the "standard ligatures" which the font manufacturer thinks should be used in normal conditions. Microsoft has a list of the OpenType feature names here.

Other special ligatures need to be explicitly enabled in Prince to take effect. This is achieved by using the font-variant CSS property with the prince-opentype() function (see CSS Functional Expressions). Care must be taken in which order the features are enabled! And please note that enabling one feature will disable all the default features. To see which OpenType features are enabled by default, see the OpenType Features in Prince section.

@page {
    font-variant: prince-opentype(dlig, liga);
}

Unlike other ligature features, the clig feature specifies the context in which the ligature is recommended. "Contextual ligatures" are important in some script designs.

The dlig feature covers the "discretionary ligatures" which may be used for special effects.

Some ligatures were in common use in the past, such as ligatures with the so-called "long s" - but they appear anachronistic today. Some fonts include the historical forms as alternates, so the "historical ligatures", covered by the hlig feature, can be used for a 'period' effect. This feature replaces the default (current) forms with the historical alternates.

Some scripts, most notably Arabic and Syriac scripts, require certain ligatures to be used in normal conditions. These "required ligatures" are covered by the rlig feature. Prince enables this feature by default in Arabic script.

Another mechanism for replacing characters is given with the prince-text-replace property. For an example use, please see the section on Character Entities.

Watermarks

You need
Page regions
  • @prince-overlay
Generated content in page regions
Taking elements from the document

When producing a PDF, it might be desirable to include a watermark, visible on all pages. In Prince it is easy to do so with CSS.

In order to repeat it on all pages, the watermark needs to be placed in a @page at-rule. We shall place it in the page region @prince-overlay (see Page regions) and create the watermark with generated content (see Generated content in page regions):

@page {
   @prince-overlay {
      color: rgba(0,0,0,0.8);
      content: "Watermark";
      font-size: 20pt;
   }
}

The overlay can be styled in all possible ways and it can be aligned in other places than middle center:

@page {
   @prince-overlay {
      content: "Watermark";
      vertical-align: top;
   }
}

Currently it is only possible to have one overlay, but you could flow an entire element having multiple individually positioned contents (see Taking elements from the document).

The styled watermark can be saved into a watermark.css file, which will be called when generating the document:

prince --style=watermark.css myfile.html -o myfile_with_watermark.pdf

Rotating content

Sometimes it is necessary to rotate a block element so that it fits on the page. This is common with tables. Two approaches are possible: either the whole page is printed sideways, or only the content in a table cell is rotated. We shall see each approach separately.

Printing wide content sideways

You need
prince-rotate-body
prince-shrink-to-fit

Figure Printing a big table sideways shows a table, rotated so that its width fits within the page's length. This can be achieved with the following rules:

Printing a big table sideways
Image of a large table printed sideways so that its width fits            along the page's length.
This table is too wide to fit on the paper, so we use prince-rotate-body in a named page to print it sideways. Download the PDF or the HTML.
@page big_table {
    prince-rotate-body: landscape;
    prince-shrink-to-fit: auto;
}

table.big {
    page: big_table
}

The prince-rotate-body property works within @page rules only, so this example uses a named page to place the table on a page of its own. Then the @page rule for big_table pages uses the prince-rotate-body property to tell prince that the body of the page, but not the headers and footers, should be rotated. The table in this example is still too wide so we also use the prince-shrink-to-fit property to make it a little smaller.

If you download the full example (HTML or PDF) you will see that the paragraphs before and after the table are not placed on the same page. This is because they do not belong to the same named page (see Named pages). However on page four there are two tables, both tables belong to the same named page and therefore Prince will try to place them together on the same page.

Another way of rotating content is by changing the writing mode with the writing-mode property, or by transforming an element with transform: rotate() - see Rotating content in table cells.

Rotating content in table cells

You need
transform: rotate()
writing-mode

There are cases, when preparing a table with a large amount of content, that you would like to configure your layout to be most efficient - a useful trick is to rotate the content in some table cells, or in the table headers. Rotating by 90° might be a way to achieve this, but readability suffers. A reasonable compromise is to rotate 45° only - the space it needs is not more than with a 90° rotation, and your readers don't have to tilt their heads repeatedly. In the following example we shall rotate table headers by 45°.

The rotation is achieved with transform: rotate(). It could be applied directly to the th element, but it is impossible to configure the width of the column as we wish it. We shall thus nest a div and a span element:

<th class="rotate">
  <div>
    <span>Column header 1</span>
  </div>
</th>

The rotation will happen with the following CSS code:

th.rotate {
  /* Make sure the th is high enough, */
  height: 150px;
  /* and make sure the words of the header are not split with a newline. */
  white-space: nowrap;
}

th.rotate > div {
  transform:
    /* Magic Numbers to put it in place, */
    translate(25px, 50px)
    /* rotate it, */
    rotate(-45deg);
  /* and give the div the width you wish. */
  width: 30px;
}
th.rotate > div > span {
  /* And finally, add some styling. */
  border-bottom: 1px solid #ccc;
  padding: 5px 10px;
}

A more basic means for rotation, allowing for less fine-tuning, is the use of the writing-mode CSS property. This option only allows rotation by 90°. It can be very handy when only some table cells with too much content are rotated, so as not to use too much horizontal space. You cannot rotate the table cell directly, so you have to nest one span element inside - and then you style it:

td.rotate > span {
  /* Rotate the content */
  writing-mode: vertical-rl;
  /* Optionally, you can force the table cell's content not to wrap */
  white-space: nowrap;
}

For a different approach to rotating content, see the section on Printing wide content sideways.

The "Two-Pass" Solution

You need
JavaScript in Printed Media
Event Handling
Console Access
  • console.log()

One limitation of producing a document intended for print is its non-interactive, static nature: a document cannot be modified after it is deemed to be ready for print. See JavaScript in Printed Media.

JavaScript can be run twice only: the first time it is run before layout, where it interacts with and modifies the layout (and the DOM structure). Once layout is finished, JavaScript can be run a second time from the complete event handler - see Event Handling. However, this time it is only allowed to inspect the layout and cannot modify the DOM.

A problematic situation arises when you want to modify your document after layout has finished - a typical scenario would be when you want an index to be created with correct page numbers. The content depends on the layout of the document itself.

(Please note that this only affects the creation of an index - a simple table of contents or a reference to a place on another page can easily be achieved with target-counter links.)

Typically Prince is run a first time to prepare the layout of the document and run JavaScript after layout has finished, collecting the output of the script to append it to the document with the help of the console.log() - see Console Access.

Now the document would be ready for generating the PDF - Prince is run a second time, producing the desired document.

Here is a minimalistic two-pass solution where the document is adorned with a ToC and index:

wget http://www.princexml.com/howcome/2015/index/musick.html -O musick.html;
  prince --javascript musick.html >>musick.html;
  prince --javascript musick.html -o musick.pdf

Another use of the two-pass solution is to create changebars - see the description here.

Documentation in PDF Format

Documentation for Prince can easily be viewed online in the browser. But there might be circumstances when it is convenient to have the documentation in one file, stored locally - and which format would be most suitable, if not PDF?

And since Prince is a tool for creating PDF files from HTML, it could also be your choice of tool to create a PDF version of the documentation!

The HTML version of the documentation is served in three distinct files:

  • the Installation Guide,
  • the User Guide for the latest version, and
  • the References.

Additionally, each file needs a few more files to display correctly - including images, CSS files to style the documents, as well as JavaScript files, necessary not just for browser-only features like scrolling to the right place in certain circumstances, but also for the core of the Prince JavaScript Support documentation.

To create a PDF version of the documentation we need to run just one simple command line:

prince --javascript http://www.princexml.com/doc/ http://www.princexml.com/doc-prince/ http://www.princexml.com/doc-refs/ -o prince-documentation.pdf

This command produces the documentation in PDF format, including a cover page, the User Guide and the References section.

If you are using the Prince GUI on Windows, you need to paste the three URLs for the cover page, the User Guide and the References by selecting the option "Add URL" three times. Next, you select the checkbox "Merge all documents into a single PDF file" and select a location where to save this file to. Make sure that the checkbox for "Enable Document Scripts" is checked, and click on the "Convert" button to convert the documents into your documentation in PDF format.

The Installation Guide is not included: since Prince is needed to create your documentation PDF, we assume that you have already installed it!

Help

The Prince User Guide tries to be exhaustive in explaining how to use the application and its features. However, there might always be something not answered in the documentation, or something not working as expected. There are a couple of ways to get help to solve the problems:

  • The Troubleshooting section addresses possible common issues after installing and starting to use Prince;
  • The Frequently Asked Questions section provides answers to the most frequently asked questions;
  • The forum is an excellent place where to find an answer to an issue, or where to ask for help;
  • You can contact us for support.

Troubleshooting

We work hard to make Prince work on multiple platforms (Windows, Linux, etc) and with multiple configurations. However things don't always work correctly the first time. You're very welcome to contact us for support or visit our forum. However if you are facing a common problem, you may be able to find an explanation and solution below.

Output log

When running into trouble with Prince, the first thing you should do is to check for any errors. These can be found in the Prince output log.

When launching Prince from the command line, Prince will print any error or warning messages directly to the console, prefixed with error: or warning: messages. The level of verbosity, or a log file where to print all output, can be controlled with a few command-line Logging Options. A more advanced control of the output is given by the Structured Log.

When using the Prince GUI, the output log is printed to the log window on the bottom left of the main GUI window.

Image formats

Symptom
prince: ./picture.bmp: warning: Unknown image format
Explanation

Prince supports JPEG, PNG, TIFF and GIF images as well as SVG (see Images). If you try to format a document that includes images in a format that is not supported by Prince, such as BMP, you may see the above error message from Prince.

Solution

The solution is to convert the image file into a format that is supported by Prince. We suggest PNG, which is a well-supported general purpose image format with lossless compression.

The capture/replay system

Prince offers a convenient capture/replay system with the two command-line options --capture and --replay - the former saving a copy of all the information in a job to a specified directory, including the input document(s) and all of the resources referenced by them and on the command line (including remote HTTP resources), such as style sheets, images, JavaScript files, fonts, etc., conveniently allowing it to be replayed later for debugging purposes with the latter command-line option. The directory might contain sensitive information (as far as included in the PDF job), so we recommend only submitting them by email when requested to do so, instead of posting them on the forum.

Running the debug script

For assisting in tracking down difficult platform bugs, the princedebug script is available on Linux and MacOS X platforms. It is located in /usr/lib/prince/bin and runs Prince with the specified command-line arguments, dumping a considerable amount of debug information to two files in the /tmp directory, namely prince.debug and prince.strace.

These files contain information about the system and environment in which Prince was run, and about the job in question, so we recommend only submitting them by email when requested to do so, instead of posting them on the forum.

The princedebug script is not available on Windows.

Frequently Asked Questions

Why do I see garbled characters on my page?

This usually happens when Prince is not able to find a suitable font, or might be using the wrong font. Try installing a font that supports your script, or try using a different font in your stylesheet. See also: Fonts and Redefining the generic font families.

Why is all the content displayed on one page, while I was expecting it to take several pages?

Typically content displays on only one page, even though it should be much longer, because it is wrapped up:

  • in an absolutely positioned element, or
  • in a floated block element, or
  • in a single inline-block element, or
  • in an element with fixed height, or
  • in an element with overflow: hidden,

which Prince cannot split over several pages. It can happen to the whole content in a document, or to just a section of it. This issue does not affect browsers, because they don't paginate. See also: Paged Media.

How can I resize my web page to fit it on the printed page?

Prince usually takes care of reformatting a document to fit on a printed page. However, there are cases where it doesn't work as expected. Wide content can be made fit by Rotating content, or by applying the CSS property prince-shrink-to-fit, which scales down all content equally. Alternatively, the command-line option --css-dpi changes the DPI of the "px" units in CSS, which defaults to 96dpi.

We do not recommend people making a habit of using this, and instead advise to design a layout specifically appropriate for the paper being used. Or at least using relative size units.

Why does my PDF file not show the transparent background?

Different PDF profiles have different requirements - you might be generating a PDF with a version or profile which does not support transparency. The only PDF profile to support transparency is the PDF/X-4 profile. See also: PDF Versions and Profiles and Color Management and PDF Profiles.

How can I create tooltips in the PDF file?

PDF tooltips can be enabled with the CSS property prince-tooltip like this:

*[title] { prince-tooltip: attr(title) }

However, please note that tooltips are not a standard PDF feature, and they may only work in Adobe Reader and Adobe Acrobat and may not be visible in other PDF viewers, such as web browsers.

How can I make an element, such as an image or some text, appear on each page of the PDF document?

For this purpose you can use the @page page regions. See: Page regions and Watermarks.

How can I apply CSS styles in page regions?

You cannot add style to generated content in the page regions, except for some inline style properties, such as color and font. A possibility for using more complex styling is to use the element() or flow() CSS functions. See Generated content in page regions, Copying content from the document and Taking elements from the document - however, this latter approach will remove the element from the document itself.

How can I start counting pages on a left page and display a right page as second page?

You can specify break-before:left | right on the root element of the document.

CSS

body[start=even] {
  break-before:left;
}

HTML

<body start="even" startpage="28">

Does Prince support JavaScript?

Yes, Prince supports JavaScript - remember to enable it with the --javascript command-line option (see Applying JavaScript in Prince). However, there are some limitations: Prince produces printed documents, and interactive events make no sense in this context. Also, modifications of the document after layout has finished are not possible. See: Scripting.

Can I modify the document after layout has finished?

No, unfortunately this is part of the inherent limitations of printed media - see JavaScript in Printed Media. However, JavaScript can run after layout is done, and the output can be used for a second run of Prince - see The "Two-Pass" Solution.

Can I include content of external files in my document?

Yes. In XML, this is done by means of XML Inclusions (XInclude). Note that XInclude is disabled by default, and can be enabled with the --xinclude command-line option. Also note that XInclude only applies to XML files.

To apply it to HTML files, the XML input format needs to be specified with the --input command-line option.

Another option in HTML is to use the iframe element:

<style>
@page {
  @bottom {
    border: solid red thin;
    content: flow(footer)
  }
}
.footer {
  flow: static(footer)
}
</style>
<iframe class="footer" src="http://www.google.com"></iframe>
<p>Normal content</p>

However there may be some subtleties required to get the correct size and styling of content within iframe elements.

Yet another option would be to use JavaScript to issue an XMLHttpRequest, parse the text of the response with DOMParser, then extract the elements and copy them into the main document. However, it will be tricky to support nested styles this way.

Prince Input

Prince takes HTML or XML files as input, and converts them to PDF files. Additionally, CSS style sheets can be provided for styling the documents, and JavaScript files can be used for additional manipulation of the input.

See the sections Applying Style Sheets in Prince, Applying JavaScript in Prince and XML Input for details.

The input files can be provided in several ways:

  • the command line (see Command-line Reference),
  • the GUI, or
  • through wrapper scripts (see Server Integration).

Input files can either be local files, or remote files that will be fetched over HTTP or HTTPS, in which case the URL to the file, or to the site, needs to be provided. Prince will automatically create the PDF output once the input pages and files have finished loading.

Applying Style Sheets in Prince

Prince can apply style sheets from three different sources:

User style sheets
  • specified from the command line interface or the GUI
Author style sheets
  • referenced from HTML using <link rel="stylesheet" ... />
  • specified in HTML using the <style> element
  • referenced from XML documents using the xml-stylesheet processing instruction
Default style sheets
  • applied automatically depending on the type of the document being formatted

Importing Style Sheets

Style sheets may import other style sheets using @import rules. These rules must occur before any other rules or declarations in the style sheet, and have the effect of importing all the rules and declarations from the specified style sheet. See CSS At-rules.

@import "base.css";
@import "custom.css";

/* more declarations */

Conflicting Declarations

Multiple style sheets can be applied and in some cases declarations from different style sheets may conflict. For example, one style sheet might specify that heading elements should use the Times New Roman font, while a different style sheet might specify that heading elements should use the Arial font:

First style sheet:

h1 {
    font-family: "Times New Roman";
    font-size: 24pt;
}

Second style sheet:

h1 {
    font-family: "Arial";
    color: red
}

In the above example, the font-family declarations conflict, and only one can possibly be applied. However, the font-size and color declarations do not conflict, and thus both will be applied to the h1 element.

Priority Determination

Style sheets are applied using a cascading process that calculates a priority for each declaration. Conflicting declarations are resolved by choosing the declaration with the highest priority and ignoring the remaining ones.

Priority is determined by looking at the origin of the declaration and whether or not it is labeled with !important.

  1. Default style sheets (lowest priority)
  2. User style sheets
  3. Author style sheets
  4. Author style sheets, !important declarations
  5. User style sheets, !important declarations (highest priority)

If the conflicting declarations have the same origin and importance, the priority is determined by comparing the specificity of the selectors used to apply them. (Combinations of selectors have even higher priority).

  1. Universal selector, eg. "*" (lowest priority)
  2. Type selector, eg. "h1"
  3. Attribute, Class and Pseudo-class selectors
  4. ID selectors, eg. "#id" (highest priority)

If the conflicting declarations have the same specificity, the declaration that occurs last in the style sheet has the highest priority.

If the declarations are from different style sheets, the declaration that occurs in the last style sheet to be specified has the highest priority. This is based on the order that style sheets are specified on the command line and also on the order that xml-stylesheet processing instructions occur in the document.

Applying JavaScript in Prince

Prince is not running JavaScript by default - document scripts can be enabled by specifying the --javascript option on the command-line. Prince will then execute all JavaScript found in the HTML script elements in the input document.

External scripts can be run by specifying one or more --script=FILE options on the command-line. These scripts will always be executed, regardless of whether document scripts have been enabled or not.

JavaScript functions can also be called from CSS generated content, by using the prince-script() syntax for referencing Script Functions. Please note that scripts contained prince-script() are treated as document scripts, and hence need to be explicitly enabled.

XML Input

XML Input

Prince processes well-formed XML 1.0 documents with full support for namespaces, internal and external entities, DTDs, character references and CDATA sections. Comments and processing instructions are ignored and do not affect the output.

Validation

Prince loads DTD files in order to resolve entity definitions and default attribute values. However, Prince does not perform validation upon input documents. If validation is a processing requirement, the use of an external validator is recommended.

xml:lang

Prince supports the xml:lang attribute, which is used to indicate the language of the document text. Elements can be selected by language using the CSS :lang() selector.

xml:id

Prince supports the xml:id attribute, which is used to give elements a unique identifier. This identifier can be used when creating links and cross-references; it also allows elements to be selected using the CSS ID selector.

xml:base

Prince does not support the xml:base attribute, therefore hyperlinks must be absolute URLs or relative to the document path.

XML Styling

Prince provides sensible default styling behavior for several common XML vocabularies:

(X)HTML
Prince styles HTML or XHTML documents by applying a default style sheet for formatting headings, paragraphs, tables, lists, inline elements and images. The default style sheet can be overridden or extended by user or author style sheets - see Applying Style Sheets in Prince.
DocBook
Prince styles DocBook documents by applying a default style sheet for formatting headings, paragraphs, tables, lists, inline elements and images. The default style sheet can be overridden or extended by user/author style sheets. (Note that Prince does not process DocBook documents expressed in SGML).
SVG
Prince supports a rich subset of SVG 1.1, including basic shapes, paths, text and transformations. All svg elements are treated as replaced elements, similar to img elements in XHTML, and their content is rendered in a rectangular space. No line breaks or page breaks are made within an svg element. (See Scalable Vector Graphics (SVG) for details of which elements are supported).
Any other XML
No default style sheets will be used, so style sheets will need to be specified by the user or referenced from the document in order for Prince to apply style to the document - see Applying Style Sheets in Prince.

Prince does not support XSLT. External XSLT processors can be used and the resulting document can be passed to Prince.

XML Inclusions (XInclude)

XML Inclusions (XInclude) provides a method of including content from other files into an XML document. When Prince processes the XML document, the inclusions are resolved and the included content is treated as if it had been in the original document all along.

The core of XInclude is a single element, <include href="..."/>, which specifies the inclusion of the file referenced by the href attribute. The element is in the XInclude namespace, http://www.w3.org/2001/XInclude, which must be declared either on the element itself or one of its ancestor elements.

Please note that XInclude is disabled by default, and can be enabled with the --xinclude command-line option. Also note that XInclude only applies to XML files. To apply it to HTML files, the input format needs to be specified with the --input command-line option.

Including XML files

Here is an example of a book written in XHTML in which each chapter has been placed in a separate XML document for convenient editing and then included in the main document using XInclude:

<html xmlns:xi="http://www.w3.org/2001/XInclude">
<head>
<title>Book Title</title>
</head>
<body>
<xi:include href="chap1.xml"/>
<xi:include href="chap2.xml"/>
<xi:include href="chap3.xml"/>
</body>
</html>

(Note that the XInclude namespace was defined on the root element and bound to the xi prefix to save space by avoiding the need to declare the namespace on every inclusion).

Including text files

XInclude can also be used to include text files into XML documents:

<xi:include href="file.txt" parse="text"/>

This is a convenient way of including files containing arbitrary non-XML text, such as emails, database reports or program source code. It also allows the inclusion of external XML content as "unparsed text", as if all the markup had been explicitly escaped with character entities or placed in a CDATA section.

Fallback

It is possible to specify fallback content that should be used if an included file cannot be loaded. The fallback content can be arbitrary XML and may even contain additional inclusions.

<xi:include href="report.html">
    <xi:fallback>
	<p>No report is available</p>
    </xi:fallback>
</xi:include>

If the report.html file cannot be loaded then the paragraph saying "No report is available" will be included in the document instead.

Prince Output

Prince produces PDF files that are compatible with Adobe Acrobat and other PDF viewers. The output can be controlled in several different ways, addressing different aspects of the resulting files.

For the error and warning output log, please see Output log.

PDF Versions and Profiles

The PDF files produced by Prince conform to several different PDF versions, up to PDF 1.7, depending on the chosen PDF Profile and the enabled PDF features.

Prince supports tagged PDF files and optional PDF profiles, which can be selected using the --pdf-profile option on the command-line interface, or the setProfile method if using a server wrapper, or the PDF.profile function in JavaScript.

The available profiles, and the PDF version they are based on, are:

PDF Profile PDF version
PDF/A-1a PDF 1.4
PDF/A-1b PDF 1.4
PDF/A-3a PDF 1.7
PDF/A-3b PDF 1.7
PDF/UA-1 PDF 1.7
PDF/X-1a:2001 PDF 1.3
PDF/X-1a:2003 PDF 1.4
PDF/X-3:2002 PDF 1.3
PDF/X-3:2003 PDF 1.4
PDF/X-4 PDF 1.6

Prince supports files with the combined PDF/A-1a+PDF/UA-1 and PDF/A-3a+PDF/UA-1 profiles.

Prince also uses:

PDF 1.5
  • if object streams are enabled, or
  • if tagged PDF is enabled, or
  • if 16-bit images are included in the PDF;
PDF 1.6
  • if the prince-pdf-print-scaling property is set, or
  • if the prince-pdf-page-mode property has the value show-attachments;
PDF 1.7
  • if the prince-pdf-paper-tray property is set, or
  • if the prince-pdf-duplex property is set.

To enable tagged PDF without using one of the profiles that already imply it, the command-line option --tagged-pdf can be used.

Prince supports PDF object streams to reduce the size of tagged PDFs. This can be disabled by the command-line argument --no-object-streams or from JavaScript via the PDF.objectStreams boolean property.

Object streams are enabled by default, therefore Prince produces files with PDF version 1.5 - unless a profile that requires older PDF versions will automatically disable object streams.

Choosing one profile over another can help producing a PDF file which has the right properties for its intended destination. Each PDF profile places restrictions on the features allowed in a PDF file in order to achieve its aims. Please also see the Color Management section for the impact the PDF profiles have on color management. Prince produces error messages when the restrictions are not respected.

$ prince foo.html --encrypt --no-embed-fonts --pdf-profile="PDF/A-1b"
prince: error: PDF/A-1b does not support encryption
prince: error: PDF/A-1b requires fonts to be embedded

Generally speaking, PDF/A profiles were created with the goal of long-term preservation of the documents (PDF for Archiving), while PDF/X profiles were created to address publisher's needs in the graphic arts industry (PDF for eXchange). The PDF/UA profile is a standard for producing accessible electronic documents (PDF for Universal Accessibility).

PDF/A

  • PDF/A tries to maximize device independence
  • Audio and video content is forbidden
  • All fonts are embedded
  • Colorspaces should be specified in a device-independent manner: all color data must be Grayscale, CMYK or named Spot Colors and there must be an output intent. Transparency is not allowed. See also Color Management and PDF Profiles
  • Encryption is forbidden

PDF/UA

  • Content must be tagged in a logical order
  • Tags must correctly represent the semantic structure (headings, lists, etc.)
  • Content not accessible to assistive technology must be avoided
  • Meaningful images and graphics must contain alternative text descriptions
  • Security settings must allow assistive technologies to access the content
  • All fonts must be embedded
  • Text must be mapped to Unicode

PDF/X

  • PDF/X is intended to support "blind exchange", i.e. no exchange of technical information is needed to render the printed page as intended
  • Audio and video content is forbidden
  • All fonts are embedded
  • Colorspaces must be specified in a device-independent manner - an output intent is required (see the --pdf-output-intent command-line option in the PDF Output Options section)
  • See the Color Management and PDF Profiles section for the color profiles available in each PDF/X version. Transparency is not allowed, with the exception of PDF/X-4
  • Encryption is forbidden

PDF Features

Prince supports a wide range of PDF features, including the following:

PDF Links

Prince supports PDF-internal and -external links. HTML hyperlinks are automatically converted. To make an element in XML, or any arbitrary element, a clickable link, the prince-link CSS property is required.

xref {
    prince-link: attr( linkend )
}

The property prince-pdf-link-type may be used to control whether relative links should be embedded in the PDF as web (URL) links or file links. By default they will be resolved against the base URL of the input document.

Prince also supports the following PDF-specific fragment identifiers, supported by web browsers, and will use them when generating links to local PDF files.

<a href="test.pdf#page=2">...</a>

<a href="test.pdf#nameddest=section1">...</a>

Named destinations (nameddest) in PDF files have a similar function to HTML IDs: they can be the target anchors for links from other documents. The property prince-pdf-destination is used for creating them.

HTML

<div class="section" data-sectionid="section1">

CSS

div.section {
    prince-pdf-destination: attr( data-sectionid )
}

In order to link to this section, the following syntax is used:

HTML

<a href="test.pdf#nameddest=section1">...</a>

PDF Actions

Prince supports the pdf-action: URL scheme for PDF actions. Typical values are Print, GoBack, GoForward, NextPage, PrevPage, FirstPage, LastPage.

<a href="pdf-action:Print">Print Document</a>

However, Prince passes the provided values verbatim to the PDF viewer, so the user can supply values that Prince doesn't know about, but the viewer does.

Please be advised that this and the following actions and scripts are dependent on the PDF viewer, and in many cases might only work in Adobe Acrobat products.

The property prince-pdf-open-action may be used to specify a space-separated list of actions to perform when the PDF file is opened, like eg. popping up the print dialog box automatically, or setting the default zoom level for PDF documents. Any arbitrary identifier can be specified, although these may be PDF viewer specific; Acrobat can take just about any menu item.

@prince-pdf {
    prince-pdf-open-action: zoom(fit-page) print;
}

In a similar fashion, JavaScript code that will be executed when the PDF file is opened may be included with the prince-pdf-script property. A common use case is to activate the "Print" dialog automatically. To achieve the equivalent of the previous example, the following code could be used:

@prince-pdf {
    prince-pdf-script: "this.zoomType = zoomtype.fitP; this.print();"
}

PDF Pages

Prince allows for some degree of control on the pages and the page layout in a PDF file. The CSS property prince-pdf-page-label can be used to set the page label that will be displayed in the PDF viewer. It can be used to instruct the PDF viewer to display the page label in the ToC in a particular way.

@page {
    prince-pdf-page-label: counter(page, lower-roman);
}

The property prince-pdf-page-mode can be used to set the default page mode for the PDF file when it is opened. For example, whether the bookmarks panel should be displayed, and whether the viewer should be fullscreen.

@prince-pdf {
    prince-pdf-page-mode: fullscreen;
}

Also the default page layout for the PDF file when it is opened can be determined with the prince-pdf-page-layout property.

@prince-pdf {
    prince-pdf-page-layout: two-column-right;
}

The values of this property are mapped to PDF page layout options:

CSS Keyword PDF Page Layout Description
single-page Single Page View Displays one page at the time
one-column Enable Scrolling Displays pages in one continuous vertical column
two-column | two-column-left Two Page Scrolling Displays facing pages side by side in a continuous vertical column - the first (i.e. cover) page is on the left.
two-column-right Two Page Scrolling & Show Cover Page Displays facing pages side by side in a continuous vertical column - the first (i.e. cover) page is displayed alone on the right.
two-page | two-page-left Two Page View Displays a two-page spread at the time - the first (i.e. the cover) page is on the left.
two-page-right Two Page View & Show Cover Page Displays a two-page spread at the time - the first (i.e. the cover) page is displayed alone on the right.

PDF Printing

Prince also provides two properties to fine-tune the printing of the PDF. The property prince-pdf-print-scaling can be used to disable print scaling for the PDF file when it is printed and the property prince-pdf-paper-tray controls the PickTrayByPDFSize flag in generated PDF files, which specifies whether the PDF page size is used to select the input paper tray.

PDF Compression

Prince compresses its PDF output to reduce the size of the documents that it produces, but does not create linearized PDF files, as this would increase formatting time and memory requirements. An external program such as Adobe Acrobat or Ghostscript may be used for this purpose if necessary.

Compression may be disabled with the command-line option --no-compress.

PDF Encryption and Restriction

Prince can encrypt the produced PDF files with the --encrypt command-line option. The default key size is 128 bits. With the option --key-bits a different key size can be chosen. Also the JavaScript methods PDF.encrypt and PDF.keyBits can be used for the same purpose.

The command-line options --user-password and --owner-password set respectively the PDF user password and the PDF owner password.

Prince also offers a range of command-line options to disallow printing, copying, annotating and modifying the PDF output: --disallow-print, --disallow-copy, --disallow-annotate and --disallow-modify.

PDF Font Embedding

Prince embeds fonts in its PDF output to ensure accurate viewing and printing on any system. Typically, only the necessary parts of a font will be embedded.

When disabling font subsetting with the command-line option --no-subset-fonts, Prince will embed the entire font in the PDF file, which is convenient if people are planning on editing the PDF file later, and may need to add glyphs that were not present in the original PDF.

Font embedding can be disabled if necessary, for example if Prince is being used to create PDF files in a controlled environment with known fonts where space is at a premium. The command-line option --no-embed-fonts is used for this purpose.

PDF Bookmarks

Prince can create PDF bookmarks that link to document content.

Bookmark levels

PDF bookmarks have numeric levels that place them in a bookmark hierarchy. For example, a bookmark at level 2 can contain nested bookmarks at level 3, or any higher level. The level of a bookmark is controlled using the prince-bookmark-level property, shown here being applied to the XHTML heading elements:

h1 { prince-bookmark-level: 1 }
h2 { prince-bookmark-level: 2 }
h3 { prince-bookmark-level: 3 }
h4 { prince-bookmark-level: 4 }
h5 { prince-bookmark-level: 5 }
h6 { prince-bookmark-level: 6 }

The default value for this property is none, which inhibits the creation of a bookmark for the element.

It is possible to control the state of the bookmark, i.e. whether the bookmark is in an open or closed state, with the prince-bookmark-state property. In this way you can close each chapter and hide the subsections for documents that are very long, or you can choose to have a deep bookmark tree.

Bookmark labels

PDF bookmarks have textual labels that by default are copied from the text content of the element that generated the bookmark. The text of this label may be controlled using the prince-bookmark-label property, shown here being applied to a chapter element that has a title attribute:

CSS

chapter {
    prince-bookmark-level: 1;
    prince-bookmark-label: attr(title)
}

This property can take any content value, including literal text strings and counters. See Generated Content Functions.

Bookmark targets

PDF bookmarks are links that display a particular part of the document when activated. By default, a bookmark will link to the element that generated the bookmark, which is sensible behavior for bookmarks generated from headings or chapter elements. It is also possible to change the target of a bookmark using the prince-bookmark-target property, which takes a URL directly or an attribute containing a URL:

CSS

bookmark { prince-bookmark-target: url(#intro) }
bookmark { prince-bookmark-target: attr(href) }

The default value for this property is self, referring to the element that generated the bookmark.

PDF Tags

Tagged PDF files have special handling mechanisms for specific tag types. In Prince, it is possible to assign PDF tag types to elements in the document through the prince-pdf-tag-type property, in order to create XML vocabularies in the PDF.

CSS

ul.toc {
  prince-pdf-tag-type: TOC;
}
.toc li {
  prince-pdf-tag-type: TOCI;
}

HTML

<ul class="toc">
  <li>First Chapter</li>
  <li>Second Chapter</li>
</ul>

Bruce Lawson has written an interesting introduction on how to make accessible tagged PDFs with Prince - all you need to know about PDF tags and Prince!

PDF Metadata

Prince creates PDF metadata from the content of the XHTML metadata elements. The content of the <title> element is used for the document title, while the <meta> element can be used to specify the document author, subject, keywords, date, and generator application:

XML

<html>
<head>
<title>Cooking with Cabbage</title>
<meta name="author" content="John Smith"/>
<meta name="subject" content="An interesting book about food"/>
<meta name="keywords" content="cabbage, cooking, eating"/>
<meta name="date" content="2009-04-01"/>
<meta name="generator" content="MyReportingApp"/>
</head>

XMP Metadata

Additionally, XMP metadata can be added to a PDF file from an XMP file. This file needs to be passed to Prince either via the --pdf-xmp command-line option, the prince-pdf-xmp CSS property, or it can be specified in JavaScript with the PDF.xmp() function.

The PDF.xmp() JavaScript function, the prince-pdf-xmp CSS property and the --pdf-xmp command-line option require either a URL pointing to an XMP file, or an encoded data: URL.

Prince includes data from the <x:xmpmeta> element and its contents. The xpacket processing instructions are ignored, as Prince generates those itself when it produces the PDF file.

Prince Networking

Prince can process local files or fetch them from remote locations. To do this, a full URL needs to be provided, including the protocol.

prince http://example.com/path/file.html -o out.pdf

Authentication

If authentication is required for the URL, the credentials can be passed by means of the --auth-user and --auth-password command-line options. A more cautious way is to add the --auth-server option, which sends username and password credentials to the specified server only - the default is to send them to any server which challenges for authentication. The option --auth-scheme sends username and password credentials only for requests with the given scheme, either HTTP or HTTPS, while --auth-method specifies a comma separated list of HTTP authentication methods to enable. Valid entries are: basic, digest, ntlm and negotiate.

A shorthand command-line option for authentication is --auth, which specifies a URL with credentials for HTTP authentication: [SCHEME:]//USER:PASS@HOST[:PORT]. Unlike the preceding options, it may be used multiple times. The username and password must be percent-encoded.

The advanced command-line option --no-auth-preemptive instructs Prince not to send credentials to named servers until an authentication challenge is received. When multiple authentication methods are enabled, an initial request may be required to discover the methods supported by the remote site.

Cookies

If cookies are required, the --cookie command-line option can be used to set a value for the Set-Cookie HTTP header value. The option may be used multiple times. Alternatively, the option --cookiejar specifies a file containing HTTP cookies.

SSL

The command-line option --ssl-cacert specifies an SSL certificate file, while the option --ssl-capath is used to specify an SSL certificate directory.

The command-line option --ssl-version sets the minimum version of SSL to allow. It may be one of: default, tlsv1, tlsv1.0, tlsv1.1 or tlsv1.2. The value default lets libcurl choose. The option --insecure disables SSL verification. Please note that using this option is not recommended!

Prince makes use of the libcurl library to process network locations - see Acknowledgments. Please note that command-line options are passed to curl as-is. On some systems curl might use a library other than OpenSSL to handle SSL - in those cases the SSL-related command-line options might behave in a slightly different way. In case of doubt, please check your own curl documentation.

Client Certificates

Client certificates are supported on Linux with several command-line options. The --ssl-cert option specifies an SSL client certificate file, while the --ssl-cert-type option defines the SSL client certificate file type (PEM, DER) - the default is PEM. The option --ssl-key specifies an SSL private key file and --ssl-key-type is used to define the SSL private key file type (PEM, DER) - the default is PEM. Last but not least, --ssl-key-password indicates the passphrase for the private key.

On MacOS, the command-line option --ssl-cert specifies a PKCS#12 file containing a client certificate and private key. The options --ssl-cert-type, --ssl-key and --ssl-key-password are not available.

Client certificates are not supported on Windows.

Miscellaneous

If an HTTP proxy server is required, it can be specified with the --http-proxy command-line option.

The option --http-timeout can be used to define the HTTP timeout in seconds, which can be useful for slow servers.

Prince can also disable downloading multiple HTTP resources at once with the --no-parallel-downloads command-line option.

Server Integration

Prince can be used server-side to produce PDFs, invoked by a wrapper script. Some care needs to be used in the configuration to make it reliable and secure.

Security and performance

When you control the input, Prince produces the expected output. But when you have no control on the input, as happens when running Prince on a server, it might be important to harden the installation in order to reduce a possible surface of vulnerability. Prince offers some options to aid the configuration, while other possibilities depend on the environment configuration on the server.

It might be a good precaution to run Prince with the command-line option --no-local-files in order to exclude any unwanted access to the local file system. It is also a good idea not to enable --xml-external-entities or --xinclude (they are not enabled by default).

A more comprehensive hardening practice is to run Prince in a chroot/jail/vms/container. Prince needs access to several libraries it depends on, as well as fonts and SSL certificates. To check direct dependencies, run the following command:

ldd /usr/lib/prince/bin/prince

When running multiple instances of Prince, it might be advisable to disable parallel rasterization with the command-line option --raster-threads=1 to improve throughput. Setting GC_MARKERS=1 in the environment will do the same for garbage collection threads.

Prince Wrappers

Since different server configurations make use of different scripting languages, wrappers in those languages are necessary to invoke Prince. Wrappers for several of the most widely used scripting languages are available for download on the Wrappers Download Page.

A useful tool for writing custom wrappers in other languages are the Advanced Command-Line Options.

For details on the usage of each of the wrappers, please consult the following chapters.

The Java Wrapper

Prince can be called from within a Java class for servlets by using Java interface.

This package contains:

  • A single JAR file (prince.jar),
  • the API documentation and
  • the Java source code for reference.

The Prince.jar file contains the class file that provides the Java interface to Prince (com.princexml.Prince). The documentation lists the Java class methods and explains how to use them.

The C# / .Net Wrapper

Prince can be called from .NET languages using the Prince C# / .Net wrapper.

The wrapper package contains:

  • the DLL file,
  • the API documentation and
  • the source code.

Using Prince with C#

To use the Prince .NET wrapper in C#, add a reference to the DLL to your Visual Studio project.

To convert HTML or XML files into PDF, instantiate a Prince object with the full path to the Prince engine executable file. Once this is done, you can apply style sheets and scripts, or configure other properties by calling the appropriate subroutines. Finally, you can call one of the Convert functions to generate a PDF file.

Please note that document scripts need to first be enabled with prn.SetJavaScript(true) - external scripts added with AddScript will always be run.

The following code sample demonstrates how to convert a single HTML document into a PDF file:

// instantiate Prince by specifying the full path to the engine executable
Prince prn = new Prince("C:\\Program Files\\Prince\\Engine\\bin\\prince.exe");

// specify the log file for error and warning messages
// make sure that you have write permissions for this file
prn.SetLog("C:\\docs\\log.txt");

// apply a CSS style sheet (optional)
prn.AddStyleSheet("C:\\docs\\css\\stylesheet-1.css");

// apply an external JavaScript file (optional) and enable document JavaScript
prn.AddScript("C:\\docs\\js\\test.js");
prn.SetJavaScript(true);

// convert a HTML document into a PDF file
prn.Convert("C:\\docs\\test1.html", "C:\\docs\\pdf\\test1.pdf");

To combine multiple HTML documents into a single PDF file, call ConvertMultiple:

String[] doc_array = {"C:\\docs\\test1.html", "C:\\docs\\test2.html"};

prn.ConvertMultiple(doc_array, "C:\\docs\\pdf\\merged.pdf");

Using Prince with VB.NET

To use the Prince The C# / .Net Wrapper in VB.NET, add a reference to the DLL to your Visual Studio project. Alternatively, you can include the Prince.vb source file directly if you prefer.

To convert HTML or XML files into PDF, instantiate a Prince object with the full path to the Prince engine executable file. Once this is done, you can apply style sheets and scripts, or configure other properties by calling the appropriate subroutines. Finally, you can call one of the Convert functions to generate a PDF file.

Please note that document scripts need to first be enabled with prn.SetJavaScript(true) - external scripts added with AddScript will always be run.

The following code sample demonstrates how to convert a single HTML document into a PDF file:

' instantiate Prince by specifying the full path to the engine executable
Dim prn As Prince

prn = New Prince("C:\Program Files\Prince\Engine\bin\prince.exe")

' specify the log file for error and warning messages
' make sure that you have write permissions for this file
prn.SetLog("C:\docs\log.txt")

' apply a CSS style sheet (optional)
prn.AddStyleSheet("C:\docs\css\stylesheet-1.css")

// apply an external JavaScript file (optional) and enable document JavaScript
prn.AddScript("C:\\docs\\js\\test.js")
prn.SetJavaScript(true)

' convert a HTML document into a PDF file
prn.Convert("C:\docs\test1.html", "C:\docs\pdf\test1.pdf")

To combine multiple HTML documents into a single PDF file, call ConvertMultiple:

Dim doc_array() As String

doc_array = {"C:\docs\test1.html", "C:\docs\test2.html"}

prn.ConvertMultiple(doc_array, "C:\docs\pdf\merged.pdf")

The PHP5 Wrapper

Prince can be called from PHP using the PHP interface.

This package contains two files:

  • The prince.php script and
  • the API documentation.

The prince.php file contains the PHP class that provides the interface to Prince. The readme.html file lists the PHP class methods and explains how to use them.

The ActiveX/COM Wrapper

The ActiveX/COM wrapper allows Prince to be called from various languages: ASP, ActiveX, COM, Visual Basic and also Coldfusion.

This package contains two files:

  • The PRINCE.dll file and
  • the API documentation.

Using Prince with ASP

Prince can be called from ASP pages using the ActiveX/COM interface.

This interface is provided in the form of an ActiveX DLL file that needs to be registered in the Windows registry using REGSVR32.EXE:

regsvr32 C:\Prince\PRINCE.dll

In order to call Prince from an ASP page, we need to create a COM object using the CreateObject server method. Once the COM object is created, you can use the COM interface methods to perform the tasks.

Please note that document scripts need to first be enabled with prn.SetJavaScript(true) - external scripts added with AddScript will always be run.

The following is some sample code for illustration:

<%
Dim pr
Dim res

Set pr = Server.CreateObject("PrinceCom.Prince")
pr.SetPrincePath "C:\Prince\engine\bin\prince.exe"
pr.AddStyleSheet "C:\Prince\css\test1.css"
pr.AddStyleSheet "C:\Prince\css\test2.css"
pr.SetJavaScript(True)
pr.SetEncryptInfo 128, "password1", "password2", true, true, true, true

If pr.Convert("C:\Prince\examples\magic.html", "C:\output.pdf") = 1 Then
    res = "Successful"
Else
    res = "Unsuccessful"
End If
%>

Using Prince with ActiveX / COM / Visual Basic

Prince can be called from Visual Basic and other languages on Windows using the ActiveX/COM interface.

This interface is provided in the form of an ActiveX DLL file that needs to be registered in the Windows registry using REGSVR32.EXE:

regsvr32 C:\Prince\PRINCE.dll

Please read the README.TXT file that comes with the ActiveX DLL file for more details of the COM interface methods.

Using Prince with ColdFusion

Prince can be called from ColdFusion pages using the Java interface or the ActiveX/COM interface, if on Windows.

Using Java

Start by downloading the Java interface for Prince. This package contains:

  • A single JAR file (prince.jar),
  • the API documentation and
  • the Java source code for reference.

The Prince.jar file contains the class file that provides the Java interface to Prince (com.princexml.Prince). The documentation lists the Java class methods and explains how to use them.

Place the Prince.jar file in a directory of your choice then start ColdFusion Administrator. Under 'Server Settings > Java and JVM', you should find 'ColdFusion Class Path'. Here you can tell ColdFusion where to look for Java classes. Type in the full path of the Prince.jar file. It should be something like: PATH\Prince.jar, where PATH is the path of the directory that contains the Prince.jar.

If this is done correctly, ColdFusion should know where to find the Prince Java interface class. The following is some sample CFML code showing how to use it:

<cfscript>
   pr = CreateObject("java", "com.princexml.Prince");

   pr.init("C:\Prince\engine\bin\prince.exe");
   pr.addStyleSheet("C:\Prince\test\test1.css");
   pr.addStyleSheet("C:\Prince\test\test2.css");
   pr.setJavaScript(true);
   pr.setEncryptInfo(128, "secretPassword1", "secretPassword2",
      True, True, True, True);

   if (pr.Convert("C:\Prince\examples\magic.html", "C:\output.pdf"))
      WriteOutput("Successful");
   else
      WriteOutput("Unsuccessful");
</cfscript>

If on Linux, substitute the paths with the appropriate UNIX style paths.

Using ActiveX/COM

If you are running ColdFusion on Windows, you can also call Prince using the ActiveX/COM interface.

This interface is provided in the form of an ActiveX DLL file that needs to be registered in the Windows registry using REGSVR32.EXE:

regsvr32 C:\Prince\PRINCE.dll

In order to call Prince from ColdFusion, we need to create a COM object using the CreateObject function that is available in CFML scripting (you can also use the <cfobject ...> tag if you prefer). Once the COM object is created, you can use the COM interface methods to perform the tasks.

The following is some sample code for illustration:

<cfscript>
   pr = CreateObject("Com", "PrinceCom.Prince", "local");

   pr.SetPrincePath("C:\Prince\engine\bin\prince.exe");
   pr.AddStyleSheet("C:\Prince\test\test1.css");
   pr.AddStyleSheet("C:\Prince\test\test2.css");
   pr.setJavaScript(true);
   pr.SetEncryptInfo(128, "secretPassword1", "secretPassword2",
      True, True, True, True);

   if (pr.Convert("C:\Prince\examples\magic.html", "C:\output.pdf") eq 1)
      WriteOutput("Successful");
   else
      WriteOutput("Unsuccessful");

   ReleaseComObject(pr);
</cfscript>

Please read the README.TXT file that comes with the ActiveX DLL file for more details of the COM interface methods.

Using Prince with Python

Prince can be called from Python using the command-line interface, like this:

import subprocess

subprocess.call(["prince","foo.xml","bar.pdf"]);

It is possible to write XML to Prince directly from the Python script rather than have Prince read it from an external file:

import subprocess

p = Popen(["prince","-","out.pdf"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

outs, errs = p.communicate("<html><body><h1>Hello, world!</h1></body></html>".encode("utf-8"))

if p.returncode :
  # Ugh.
else :
  pdf = outs

The first filename argument of "-" instructs Prince to read the XML from its standard input stream rather than from a file.

For Python CGI scripts, the PDF output can be written to the standard output stream so that it is returned to the browser:

import subprocess

p = Popen(["prince","-"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

outs, errs = p.communicate("<html><body><h1>Hello, world!</h1></body></html>".encode("utf-8"))

if p.returncode :
  # Ugh.
else :
  pdf = outs

Because the second filename argument has been omitted and the XML is being read from standard input, the PDF will be written to standard output. Be careful to redirect the output of this script if you try running it from the terminal.

Alternatively, it is possible for the Python script to read the PDF output directly rather than have Prince save it to an external file:

import subprocess

p = Popen(["prince","-"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

outs, errs = p.communicate("<html><body><h1>Hello, world!</h1></body></html>".encode("utf-8"))

if p.returncode :
  # Ugh.
else :
  pdf = outs

print("PDF is "+str(len(pdf))+" bytes in size")

Using Prince with Perl

Prince can be called from Perl using the command-line interface, like this:

system("prince foo.xml bar.pdf");

It is possible to write XML to Prince directly from the Perl script rather than have Prince read it from an external file:

open(PRINCE, "| prince - out.pdf");
print PRINCE "<html><body><h1>Hello, world!</h1></body></html>";
close(PRINCE);

The first filename argument of "-" instructs Prince to read the XML from its standard input stream rather than from a file.

For Perl CGI scripts, the PDF output can be written to the standard output stream so that it is returned to the browser:

print "Content-Type: application/pdf\n\n";
open(PRINCE, "| prince -");
print PRINCE "<html><body><h1>Hello, world!</h1></body></html>";
close(PRINCE);

Because the second filename argument has been omitted and the XML is being read from standard input, the PDF will be written to standard output. Be careful to redirect the output of this script if you try running it from the terminal.

Alternatively, it is possible for the Perl script to read the PDF output directly rather than have Prince save it to an external file:

open(PRINCE, "prince foo.xml - |");
# ... read PDF output from PRINCE file handle
close(PRINCE);

Third-Party Wrappers

There are also third-party wrappers available for download on external sites. Please note that YesLogic does not take any responsibilities for third-party wrappers offered for download on these external locations.

Ruby on Rails
A simple Rails wrapper for the PrinceXML PDF generation library
Node.js
Node API for executing XML/HTML to PDF renderer PrinceXML via prince(1) CLI

Advanced Command-Line Options

Prince can also be called from the command-line with two special options, useful for understanding the calls Prince can be controlled with, and the output it produces, in order to write your own wrapper: the Prince Control Protocol and the Structured Log.

Prince Control Protocol

prince --control

The Prince Control Protocol, accessible through the command-line option --control, is a synchronous bidirectional protocol that consists of a sequence of "chunks" sent via the standard input and output streams.

Each chunk contains a sequence of bytes with a length and a three letter tag. Here is an example "version" chunk to demonstrate the syntax:

ver 15
Prince 20161219

This chunk has a tag ver (all tags are three ASCII characters) followed by a space, then the length of the data expressed as a decimal number, then a newline character, then the data itself (15 bytes), then another newline (not part of the data).

This "version" chunk is emitted by Prince when the control protocol begins and can be used to check the Prince version and confirm that communication is functioning as expected. Prince will then wait for jobs to be submitted.

If a chunk contains no data then the length is zero and the chunk ends with the newline immediately following the length. In fact the length itself may be omitted, making this a perfectly valid chunk:

end

This end chunk consists of three letters and a newline character and can be used to terminate the Prince process when there are no further jobs to process.

Currently the control protocol includes the following chunk types sent by Prince:

  • ver, sent at startup
  • pdf, a generated PDF file
  • log, the complete output log for the job including all errors and warnings
  • err, errors relating to the control protocol itself

And these chunks sent by the caller:

  • job, the description of a requested conversion job, expressed in JSON
  • dat, a file resource needed by the job
  • end, to terminate the control connection

A typical interaction looks like this:

Prince: ver
Caller: job
Caller: dat
Caller: dat
Prince: pdf
Prince: log
Caller: end

Instead of sending the final end chunk the caller may choose to submit another job chunk and continue converting documents. The protocol is synchronous so replies simply match requests in order.

The job chunk contains a description of the conversion job represented in JSON format, which can be followed by an optional sequence of dat chunks containing file data which is needed by the job, eg. HTML documents, style sheets, PDF attachments, or whatever.

The number of dat chunks is specified by the job-resource-count field in the job description, and these files can be accessed via a special job-resource URL scheme, eg. job-resource:0 will access the content of the first dat chunk, then job-resource:1, job-resource:2, etc. This allows any number of resources to be provided inline with the request and removes the need to create actual temporary files.

The JSON job description has several nested objects with fields corresponding to Prince options:

{
    "input": { <input options> },
    "pdf": { <pdf options> },
    "metadata": { <metadata options> },
    "raster": { <raster options> },
    "job-resource-count": <int>
}

The input options and job-resource-count are mandatory, the rest are optional and will default to the normal values.

The input options object includes these fields:

{
    "src": <single URL or list of URLs>,
    "type": <string>,
    "base": <string>,
    "media": <string>,
    "styles": [ <list of URLs> ],
    "scripts": [ <list of URLs> ],
    "default-style": <bool>,
    "author-style": <bool>,
    "javascript": <bool>,
    "xinclude": <bool>,
    "xml-external-entities": <bool>
}

Only the src field is required, the rest can be left as defaults.

Now we can make some simple job descriptions, eg. to convert a single HTML file:

{
    "input": {
        "src": "/path/to/input.html"
    },
    "job-resource-count": 0
}

This can be sent as a single job chunk and Prince will respond with a pdf chunk if the conversion succeeded and a log chunk.

Or you can convert a HTML document without saving it to a temporary file:

{
    "input": {
        "src": "job-resource:0"
    },
    "job-resource-count": 1
}

This requires the job chunk to be followed by a dat chunk that contains the HTML and then Prince will respond as before.

The pdf options object includes these fields:

{
    "color-options": "auto" | "use-true-black" | "use-rich-black",
    "embed-fonts": <bool>,
    "subset-fonts": <bool>,
    "artificial-fonts": <bool>,
    "force-identity-encoding": <bool>,
    "compress": <bool>,
    "encrypt": {
        "key-bits": 40 | 128,
        "user-password": <string>,
        "owner-password": <string>,
        "disallow-print": <bool>,
        "disallow-modify": <bool>,
        "disallow-copy": <bool>,
        "disallow-annotate": <bool>
    },
    "pdf-profile": <string>,
    "pdf-output-intent": <URL>,
    "fallback-cmyk-profile": <URL>,
    "color-conversion": "none" | "full",
    "pdf-lang": <string>,
    "pdf-xmp": <url>,
    "tagged-pdf": "auto" | <bool>,
    "attach": [ <list of attachments> ]
}

Each attachment is a <url> (string) or an object:

{
    "url": <url>,
    "filename": <string>,
    "description": <string>
}

The metadata options object includes these fields:

{
    "title": <string>,
    "subject": <string>,
    "author": <string>,
    "keywords": <string>,
    "creator": <string>,
}

The raster options object includes these fields:

{
    "dpi": <integer>,
    "background": "white" | "transparent"
}

Structured Log

--structured-log=LEVEL

This option is designed to make it easier to integrate other software with Prince. It takes these values:

  • --no-structured-log
  • --structured-log=normal
  • --structured-log=quiet
  • --structured-log=progress
  • --structured-log=buffered

The default is --no-structured-log, in which case error and warning messages will be written to the terminal (stderr stream) as they occur in a human readable format, eg.

prince: foo.html: error: can't open input file: No such file or directory
prince: foo.html: error: could not load input file
prince: error: failed to load all input documents

Specifying --structured-log=normal writes the log messages in an alternate format with fields separated by | characters, in order to make it easier to parse by other software.

The first field indicates the type of message, which can be:

  • sta| = status message;
  • prg| = progress percentage;
  • fin| = final outcome, which can be
    • fin|success, or
    • fin|failure;
  • dat|name|value = data messages produced by Log.data("name", "value");
  • msg| = messages, which can be any of the following:
    • msg|err = error message;
    • msg|wrn = warning message;
    • msg|inf = information message;
    • msg|dbg = debug message;
    • msg|out = console output from console.log();
    and always followed by source location and the message itself.
msg|err|foo.html|can't open input file: No such file or directory
msg|err|foo.html|could not load input file
msg|err||failed to load all input documents
fin|failure

The last msg|err message has an empty source location field.

Specifying --structured-log=quiet suppresses all log messages, except for the final fin message, indicating success or failure:

fin|failure

This allows other software to read the stdout stream from Prince containing the PDF file in its entirety, then read the final status from the stderr stream, without worrying about blocking due to deadlocks.

Specifying --structured-log=progress prints percentage log messages for use in GUI applications:

prg|94
prg|96
prg|99
prg|100
fin|success

Specifying --structured-log=buffered is the same as normal, but all log messages will be delayed until after the full PDF has been written to the stdout stream, again so that other software can read from stdout and then read the log from stderr without deadlocking.

The deadlock problem happens when Prince writes log messages to stderr and blocks, waiting for the other software to read them, but the other software is blocked waiting for Prince to write the PDF to stdout, leading to a deadlock where both processes hang indefinitely.

By omitting log messages, or by delaying them until after the PDF is written, this deadlock can be avoided. Another option is to use the Prince Control Protocol, which also avoids this problem.

Prince for Books

Prince for Books is a new venture that allows us to spend more time on features particularly sought by publishers.

The initial focus of work is on the features common to all books: making the pagination and line-breaking choices expected of books, by featuring a few extensions to CSS and fine-tuned algorithms.

For the time being, Prince for Books is only available as a a command-line application named prince-books. It is used like the standard Prince - see Command-line Reference for available options.

prince-books OPTIONS FILES [-o PDF]

To download it, head over to the Prince for Books download page. It is available in package bundles only - to install it, the files need to be copied into place (Windows), or an installation script needs to be run (on Linux and MacOS X). It can be installed without problem alongside a normal Prince installation - the executable to run is called prince-books.

Line breaking

Prince for Books introduces a few new CSS properties to try handling line breaks in a more granular way, and additionally, it tries harder to avoid a hyphen at the end of a page and at the end of the last full line, as well as for ragged text (i.e. for left-aligned or centered text). It also tries to avoid a short last line, especially if it is shorter than the value of text-indent.

The property prince-wrap-inside

The property prince-wrap-inside offers a way to instruct Prince how to break text: the keyword phrase is for marking up a phrase that one would weakly prefer to keep on a single line. It adds to Prince's perceived cost of breaking within that phrase, but only a small cost, comparable to the cost of hyphenating a compound adjective such as ‘midyear’.

The keyword avoid is a stronger directive: it avoids breaking the text to which the property is applied even if it causes the affected text to be unusually tight, or the previous line to be unusually loose; but not if either line would become truly exceptionally tightly or loosely spaced.

This property would most commonly be used in headings, or perhaps in important passages of body text such as in instructions or for the name of a product in advertising. For example, if one opens a book that was printed before the widespread use of computers in publishing, then one would likely see that any headings that don't fit in one line won't simply put as much on the first line as fits, but will instead break somewhat according to natural phrasing.

To make it more likely for Prince for Books to produce this effect, one might put span elements around phrases, styling each of these spans with prince-wrap-inside:phrase.

HTML

<h1>The <span>fulfilment <span>of the law</span></span>
  <span>and <span>of the prophets</span></span></h1>

CSS

span {
  prince-wrap-inside: phrase;
}

The example would produce a title line like this:

The fulfilment of the law and of the prophets

If however the final available space were narrower than the required space, Prince might instead format as:

The fulfilment of the law and of the prophets

The property prince-line-break-choices

Another property for fine-tuning the line breaking behaviour is prince-line-break-choices.

The keyword title is intended for title pages of books or chapters, where phrasing considerations are of prime consideration even at the cost of extremely unbalanced lines.

The keyword heading, on the other hand, is closer to body, differing mainly in that it's less likely to hyphenate, and is more willing to make the first line(s) a little shorter if doing so avoids a short last line.

The *-lookahead keywords enable paragraph-at-a-time line-breaking for the paragraph in a non-justified paragraph: choosing where to end the line not just based on what seems best for the current line (as one might decide if using a pen or typewriter), but also considering the effect on future lines.

Enabling lookahead for a paragraph makes Prince take longer, though the results are typically slightly better: still ragged, but fewer lines that are much shorter than nearby lines.

A disadvantage of lookahead is that any "mistakes" (that is, differences from what a human would choose) risk appearing inexplicable to a reader, unlike with the non-lookahead versions where the only reason that a line would be noticeably short is where the following line starts with a long word.

This means that the non-lookahead versions might be a better choice in jobs where Prince's line breaks will be accepted without human oversight; whereas if a typesetter will look for and correct any problems in the rag of the paragraph, then the lookahead versions will typically give a better starting point.

A typesetter's intervention currently involves modifying the HTML: it is not requireed to assign an id to each paragraph, but it is nevertheless common practice to do so for making other changes, such as changing the number of lines in a paragraph for pagination purposes (whether using prince-n-lines or word-spacing or letter-spacing), or assigning a unique value to each chapter in order to change how many lines are on the last page of the chapter (say, by adding 1pt to the inside margin). See also Spread Balancing.

To illustrate the difference, one could also say that non-lookahead versions give paragraph shapes reminiscent of those given by word processors and web browsers, while the lookahead versions come slightly closer to what one might find in books.

The keyword fast can be used for quick web-browers–style line breaking, useful for testing the effect of styling changes that don't depend on good line breaking.

The base stylesheet that Prince for Books applies to all HTML documents (i.e. the "user-agent style sheet", in CSS terminology) includes the ruleset

h1, h2, h3, h4, h5, h6 {
    prince-line-break-choices: heading;
}

but HTML semantics alone do not distinguish content where the more extreme prince-line-break-choices: title could be appropriate. Doing so requires additional conventions, such as those given in the HTMLBook specification.

The below example applies title-lookahead line-breaking to the book title, chapter titles and part titles, while applying heading-lookahead line-breaking to subtitles.

CSS

body[data-type="book"] > h1,
body[data-type="book"] > heading > h1,
section[data-type="chapter"] > h1,
section[data-type="chapter"] > heading > h1,
div[data-type="part"] > h1,
div[data-type="part"] > heading > h1 {
    prince-line-break-choices: title-lookahead;
}

heading > * {
    prince-line-break-choices: heading-lookahead;
}

HTMLBook uses a slightly non-standard representation of subtitles: not using hgroup, and using p elements rather than the heading elements h1 to h6.

The property prince-forced-breaks

The property prince-forced-breaks controls whether a line ended by a "preserved newline" (such as introduced by <br>) should preferably appear to be a normal full line (as if ended only by normal line wrapping), or whether being shorter than a normal full line is actually preferable, for example to mark a deliberate break.

The br element would usually create a visually forced break, treating that line much as if it were the last line of a paragraph. For example, it would continue to do so in any UA not supporting the property prince-forced-breaks (thus getting in the way of reading the content in some other UA, or using the same source document for web/epub deployment), or if the stylesheet doesn't load. Tweaking line breaks using prince-forced-breaks: full is not intended to be consciously noticeable by readers, so br would not be the best approximation in HTML.

CSS

lb { white-space: pre; }
lb::before { content: "\A"; prince-forced-breaks: full; }

This example shows the styling for an <lb /> element, which can be added to force breaks. Of course we first need to instruct Prince to respect "preserved newlines" - we do this with the white-space property.

Literally using the element name lb in the html namespace would make the document not valid HTML. The element could be either in a non-HTML namespace, or one could use a custom element to be inserted with JavaScript.

If multiple editions are to produced from a single source document, then a variation would be

CSS

lb[ed ~= "a"]::before { ... }

in the stylesheet for edition A (and similarly for the stylesheets of other editions), and

HTML

<lb ed="a c" />

in the document where a line break should be forced only in editions A and C.

The difference is particularly marked in justified text, where lines ended by prince-forced-breaks: full are subject to justification like most other lines.

Spread Balancing

A prominent new feature is the concept of "spread balancing": Prince for Books can try to ensure that the content on two-page spreads is the same height. Due to the widows and orphans properties (see Widows and orphans) it is possible for one page to have fewer lines than the other, and this unevenness looks upsetting.

Prince for Books also tries to reduce the number of uneven spreads.

The property prince-page-fill

The property prince-page-fill is used to turn on the page balancing mechanism. Prince for Books will check how much space is left at the bottom of each page of a two-page spread and compares it with the line-height to determine whether the pages end with different numbers of lines. If one page is longer than the other, Prince will attempt to repack that page one line shorter, so that they match in height. If it is still unbalanced, which might happen due to triggering another widows/orphans constraint, it will revert to the original layout.

Prince also includes the bottom margin in the evaluation for balancing, allowing said margin to be truncated for purposes of deciding whether the two pages can be considered to have the same length.

The property prince-n-lines

Another way to address page balancing is by using the property prince-n-lines. It is for use in the pagination phase of typesetting, for ensuring that page ends are even while avoiding widows and other awkward breaks.

Typically, the best paragraph to apply this property to will be either already long and/or currently has either a very short or almost full last line, so that the paragraph doesn't need to change much in length compared to its existing "length" (as reckoned by its height). That is, the typesetter can choose a good candidate by looking at how much the last line would need to shrink or grow (including a word or two for the next line if growing), and how many times that length would fit in the height of the paragraph, with more being better.

As noted before, a typesetter's intervention currently involves modifying the HTML.

Values other than the initial value of auto request that the paragraph occupy the given number of lines; where values other than a simple integer are relative to the number of lines that the paragraph would have occupied if this property still had its initial value (auto).

The value change means to make the paragraph either a line longer or shorter, whichever will be deemed to look better. This value is provided for the common case that a page break opportunity exists both at a line earlier and at a line later than where the page end would naturally fall, as would typically be the case if the only relevant restriction arises from widows:2 or orphans:2 or a minor heading that occupies two body lines worth of height. Thus, this tends to be the most commonly used value for this property, other than leaving at its initial value.

A simple integer value is the least convenient value to use (since choosing the desired number requires counting the existing number of lines, and since this property is most commonly used on long paragraphs). Its value lies in the fact that the result is not subject to variation in "the number of lines that the paragraph would otherwise have had", as can occur if this paragraph spans a page end, and a subsequent styling change causes some earlier content to changes in size, affecting what is the last line before the break, and if this in turn affects line-breaking decisions made to avoid having a hyphenation at the end of a page.

Alternatives to adjusting a paragraph length include adding extra space around a heading, an image or at the start of a chapter.

Fractional Widows

Another feature in Prince for Books are the "fractional widows": the widows property is allowed a value expressed as percentage.

p {
  widows: 50%;
}

This indicates indicates that one widow line is accepted, as long as the line width is at least the given percentage value of the available page width, to avoid the worst case of having a widow line that is only one or two words long.

Copyright © 2002 – 2019 YesLogic Pty. Ltd.
  • About Us
  • Privacy Policy
  • Contact Us