Tips & Tricks

This page presents some tips and tricks, mostly in the form of code snippets.


These tips are primarily sourced from the community. You too can share your tricks with the community, just open a PR! (If you do so, don’t forget to make your code readable for the others and add some context :).)

Edit the generated PDF using WeasyPrint’s PDF editor

Why this snippet?

You may want to edit the PDF generated by WeasyPrint, for example to add PDF features that are not supported by CSS properties.

WeasyPrint includes a very simple and limited PDF editor that can be used in this case. This PDF editor only works with documents generated by WeasyPrint.

In this example, we will set the magnification to “Fit page”, so that the PDF size automatically fits in the PDF reader window when open.

How to use this snippet?

You can use the code below as a simple Python script. Change the URL you want to render and the path of the generated PDF to fit your needs.

If you want to add other features, you will have to read the PDF specification!

Show me the code!

from io import BytesIO
from weasyprint import HTML
from weasyprint.pdf import PDFFile, pdf_format

html = HTML('')
content = BytesIO(html.write_pdf())
pdf_file = PDFFile(content)
params = pdf_format('/OpenAction [0 /FitV null]')
pdf_file.extend_dict(pdf_file.catalog, params)
pdf = pdf_file.fileobj.getvalue()
open('/tmp/weasyprint.pdf', 'wb').write(pdf)

Display forms

Why this snippet?

Contrary to many browsers, WeasyPrint doesn’t render form inputs using a custom toolkit. As there’s no dedicated stylesheet for them, they’re often not rendered at all.

Forms could also be rendered in generated PDF files, but it’s not supported yet (see issue #61).

The easiest way to render inputs is to use a dedicated stylesheet.

How to use this snippet?

Adapt and include the sample into your document stylesheets.

Show me the code!

input, textarea {
  background: #eee;
  border: 0.01em solid;
  display: block;
  margin: 0.2em 0;

[disabled] {
  opacity: 0.3;

input[type=text] {
  height: 1.2em;
  width: 20em;

input[type=text]::before {
  content: attr(value);
  padding: 0.2em;

input[type=radio], input[type=checkbox] {
  box-sizing: border-box;
  background-clip: content-box;
  height: 1em;
  padding: 0.1em;
  width: 1em;

input[checked] {
  background-color: red;

input[type=radio] {
  border-radius: 100%;

textarea {
  font-family: monospace;
  padding: 0.5em;
  width: 20em;