WeasyPrint is software for using HTML/CSS to generate PDFs. It supports many pagination CSS features that typical browsers don’t currently support (like CSS Generated Content for Paged Media Module or CSS Generated Content Module Level 3).
Links
- Homepage
- https://weasyprint.org/
- Documentation
- https://doc.courtbouillon.org/weasyprint/stable/
- Supported CSS features
- https://doc.courtbouillon.org/weasyprint/stable/api_reference.html#css
Nix
Try out WeasyPrint in Nix with:
nix-shell -p python3Packages.weasyprint
Command Line
Check out the Command-line API documentation.
Here’s how you’d generate a PDF for some webpage:
weasyprint https://jmm.io/weasyprint weasyprint.pdf
And here’s how you’d add your own CSS stylesheets:
weasyprint --stylesheet css/common.css --stylesheet css/weasy1.css weasy-version.xhtml weasy-output.pdf
CSS
How to do some basic things in CSS for formatting PDFs:
Page numbers
Here’s some simple CSS to add page numbers to the bottom center:
@page {
@bottom-center {
content: counter(page);
position: absolute;
z-index: -1;
}
}
This comes from CSS Paged Media Module Level 3.
Landscape pages
For my dissertation, I need page numbers to stay in the same position, even in landscape pages.
Like, think about a wide table that needs to be rotated.
Normally, you could use a page-orientation: rotate-left;
style (see https://www.w3.org/TR/css-page-3/#page-orientation-prop) to achieve this, but it seems like WeasyPrint doesn’t recognize this option.
If you use the following style, the page number on the landscape page will appear in the incorrect position. That is, it’ll appear in the middle of the long edge of the paper.
@page landscape1 {
size: landscape;
page-orientation: rotate-left;
}
.somefigure {
page: landscape1;
page-break-before: always;
page-break-after: always;
}
WeasyPrint does warn saying:
WARNING: Ignored `page-orientation: rotate-left` at 18:5, unknown property.
I think the next thing I’ll try to work around this is to rotate the figure itself without changing the page.
This code rotates it, but positions it kinda weird.
.somefigure2 {
transform: rotate(-90deg);
page-break-before: always;
page-break-after: always;
}
I also tried changing the writing mode:
.somefigure3 {
writing-mode: vertical-lr;
text-orientation: upright;
page-break-before: always;
page-break-after: always;
}
But I got the warning:
WARNING: Ignored `writing-mode: vertical-lr` at 35:5, unknown property. WARNING: Ignored `text-orientation: upright` at 36:5, unknown property.
I haven’t found a good solution to this yet. I’m just going to avoid big tables for now.
Front material Roman numerals
Formatting for my dissertation states that front material be given Roman numerals and main text be given Arabic (normal) numerals restarting at number 1. I figured out how to do the Roman numerals part, that’s just this CSS:
@page frontmatter {
@bottom-center {
content: counter(page, lower-roman);
}
}
But I’m not able to reset the page counter using the following:
.maintext {
counter-reset: page;
}
WeasyPrint issue#93 mentions this.
Oh, but then it mentions pull request #631 which does show how to reset a counter! Here’s an example:
@page mainmatter {
counter-reset: page 1;
}
.maintext {
page: mainmatter;
}
Note that counter-reset: page 1;
must appear inside a @page
rule.
Including it outside it doesn’t work.
Other Issues
UTF-8 encoding
Some curly quotes (“like this”) weren’t rendering properly.
You need to make sure you have <meta charset="UTF-8"/>
in your HTML (if you’re rendering from a file).
Simply having <?xml version="1.0" encoding="UTF-8"?>
wasn’t enough.
SVG rendering
I’m getting some issues with rendering SVGs. I’ll have to investigate further and provide a minimal working example, but for now I’m just rasterizing some figures within the browser and substituting the <img> src for a data: URI of a PNG.
I may end up trying to use ConTeXt instead of WeasyPrint at some later point.