print-css.rocks lessons
print-css.rocks is Andreas Jung’s tutorial on CSS for paged media, on GitHub: 70 lessons, each a short HTML document, most with a one-line note on what it demonstrates. Jung runs 63 of them on eight engines and grades every result; the 7 that use one engine’s proprietary extensions run on that engine only. Here the ReflowPDF Engine prints 67 of them; each has its PDF and, unless it needs JavaScript, opens in the playground. The other 3 are XML documents, and the engine reads HTML.
We grade our prints the way Jung grades his engines: by eye, against what each lesson sets out to show. Where our print differs from the lesson because we follow a rule of the spec, its card says so and the note cites the rule. Jung’s grades for the other engines are in each lesson’s conversion.ini.
| Matches the lesson | 55 |
|---|---|
| Differs from the lesson, follows the spec | 5 |
| Partly matches the lesson | 0 |
| Does not match the lesson | 0 |
| Not supported | 10 |
Not supported: 3 XML lessons, 6 that use another engine’s extensions, and 1 that uses content MathML and <mfenced>, which MathML Core (the MathML browsers implement) leaves out. Lessons that match carry no label; every other lesson has a label and a note on the difference.
Against the eight engines
Jung printed the other engines between December 2023 and January 2024, in the versions listed; current versions may differ. ReflowPDF results are self-assessed the same way. The table counts the 63 lessons Jung runs on every engine. Our 5 results that differ from the lesson where we follow a rule of the spec are in their own column, Spec*, and not counted as OK: Jung has no such grade, and we give it only to our own prints. Ties list Jung’s engines first.
| Engine | OK | Spec* | Partly | Error | Unsupp. |
|---|---|---|---|---|---|
| PDFreactor 11.6.6 | 57 | – | 2 | 1 | 3 |
| Antenna House 7.4 | 55 | – | 3 | 3 | 2 |
| Prince 15.2 | 54 | – | 3 | 4 | 2 |
| BFO Publisher 1.3 | 54 | – | – | 6 | 3 |
| ReflowPDF self-assessed, build c01f2f7a6 | 54 | 5 | – | – | 4 |
| Vivliostyle 2.25.9 | 52 | – | – | 2 | 9 |
| WeasyPrint 60.2 | 46 | – | 2 | 6 | 9 |
| Typeset.sh version not recorded | 45 | – | 1 | 2 | 15 |
| Paged.js on Chrome 115 | 36 | – | – | 13 | 14 |
The other 7 lessons use one engine’s proprietary extensions, and Jung runs each only on that engine:
| Lesson | Engine | Jung | ReflowPDF |
|---|---|---|---|
| Antennahouse Autofit Text | Antenna House | OK | Unsupp. |
| Antennahouse multiple columns with sidenotes | Antenna House | OK | Unsupp. |
| PDFreactor autofit text | PDFreactor | OK | Unsupp. |
| PDFreactor mathjax | PDFreactor | OK | OK |
| PDFreactor multicol with dual sidenotes | PDFreactor | OK | Unsupp. |
| PDFreactor multicol with sidenotes | PDFreactor | OK | Unsupp. |
| Prince table tricks | Prince | OK | Unsupp. |
All lessons on all engines, with a link to each PDF.
Introduction
Chapter numbering
Cross references
CSS transformations
Differs from the lesson, follows the spec
The Tux images print on page 1 over the text, and page 5 is blank. Absolutely positioned boxes are placed as if there were no page breaks (css-position-3 §4.4), relative to the first page’s area (css-page-3 §3). Jung’s engines put them on page 5, which §4.4 also allows.
CSS transformations2
CSS transformations3
Footnotes
Editable PDF Forms
Hyphenation
Images
Differs from the lesson, follows the spec
On page 4 the photo rotated 45° reaches above the top of the sheet; that corner prints at the foot of page 3 instead of being cut off (css-break-3 §5.5). PDF images are not drawn; Jung grades Prince OK with the same limitation.
letter-spacing
CSS list style
CSS list style (2)
CSS list styles (3)
Multi columns
Named pages
Page areas
Page numbers
Pagination
Positioning
Right to left
Running elements
Advanced
Archive PDFs
Printed as PDF/A-3a; veraPDF validates it as PDF/A-3b and PDF/A-3a. The playground prints without this option.
Repeated background
Border model
Box styling
Vertical centering
CSS gradients
z-index 2
A CSS deer
Differs from the lesson, follows the spec
Prints on two pages, not one. html and body are as tall as the page area, and body’s default 8px margin pushes it past the page, so it breaks onto page 2 (css-break-3 §2). Page 2 gets the background and the fixed sun, as every page does (css-page-3 §3.1, css-position-3 §2.1). The scene starts at the 8px margin, its static position (CSS 2.1 §10.3.7), so it overflows 8px into the right margin.
Fonts emoji
Footnotes multi columns
Differs from the lesson, follows the spec
Footnotes span all columns, which the lesson allows. column-fill: auto fills columns in order (css-multicol-1 §7.1), so the end of the text fills only the first column on page 3.
Hyphenation long words
Ligatures
Metadata PDF/UA
Printed tagged as PDF/UA-1; veraPDF validates it. The playground prints without this option.
Multiple backgrounds
Named strings (set-content property)
PDF bookmarks
PDF links
attr() function
Using set-content
Using text-shadow property
Texts rotated 360 degrees
Typography
Special
Account statement example
Differs from the lesson, follows the spec
With body’s default 8px margins, the two 245.4 pt tables at the top need 490.8 pt and have 490.64 pt, so the second wraps below (CSS 2.1 §9.5.1), as in WeasyPrint. Engines that print without the body margin fit them side by side.
Blank pages
Rainbow using box-shadow
Complex CSS
Darth Vader as CSS
Image scaling
Not printed, because they are written in XML: .
JavaScript, MathML and XML
Chart JS
Printed with the
javascriptoption; the playground doesn’t run scripts.Flotr2 JS
Printed with the
javascriptoption; the playground doesn’t run scripts.Mathml native
Not supported
Content MathML and <mfenced> are not part of MathML Core; as in browsers, they render as plain rows.
Mathml torture test
Not printed, because they are written in XML: XML and XML images.
Written for one engine
Antennahouse Autofit Text
Not supported
Uses -ah-overflow-condense, an Antenna House extension.
Antennahouse multiple columns with sidenotes
Not supported
Uses -ah-float, an Antenna House extension.
PDFreactor autofit text
Not supported
Uses PDFreactor’s JavaScript layout API (ro.layout).
PDFreactor mathjax
Printed with the
javascriptoption; the playground doesn’t run scripts.PDFreactor multicol with dual sidenotes
Not supported
Uses PDFreactor’s JavaScript layout API (ro.layout).
PDFreactor multicol with sidenotes
Not supported
Uses PDFreactor’s JavaScript layout API (ro.layout).
Prince table tricks
Not supported
Uses prince-rotate-body and prince-caption-page, Prince extensions.
Every lesson, every engine
Each result links to that engine’s PDF: ours on this site, the others in Jung’s repository. Where Jung wrote a note on a result, hover the result to see it; screen readers announce it. Spec* differs from the lesson where we follow a rule of the spec; the lesson’s card above cites the rule.
Lessons © Andreas Jung, ZOPYX, published with his permission; titles are his. Playground copies omit scripts, files over 4 MB, and fonts we may not redistribute. The PDFs were printed on 8 November 2026 with ReflowPDF Engine build c01f2f7a6, the build the playground runs.