[Fixed]-Generate PDF with WeasyPrint having common header/footer and pagination

32๐Ÿ‘

โœ…

Since Weasyprint supports CSS Paged Media Module Level 3, simple headers and footers (e.g. pagination, like you mentioned) can be accomplished using CSS:

@page {
    @top-right{
        content: "Page " counter(page) " of " counter(pages);
    }
}

Make sure you include your stylesheets when rendering:

HTML(string=rendered_html,
     base_url=settings.SITE_URL).write_pdf(stylesheets=[CSS(settings.STATIC_ROOT + '/css/pdf_render.css')])

However, getting more complex headers/footers to render can be more.. complex. Some people have suggested the method of including a div element in the header that renders only for print (but I must admit I have only been able to get simple elements to render properly with this method):

@page {
    @top-left {
        content: element(pageHeader);
    }
}
@media print {
    #divHeader{
        position: running(pageHeader);
    }
}

There is also another method using fixed positions, as demonstrated in this gist: https://gist.github.com/pikhovkin/5642563

๐Ÿ‘คKeith

12๐Ÿ‘

Currently running elements are not supported by WeasyPrint. Nevertheless I found a way to achieve the same result using named strings:

 @page {
   @top-center {
     content:  string(title);
   }
 }

 header {
   width: 0;
   height: 0;
   visibility: hidden;
   string-set: title content();
}

Now you can add your content to an invisible HTML header element.

<header>Content of the header goes here</header>
๐Ÿ‘คadonig

3๐Ÿ‘

I could get this to work simply by using position: fixed for the header and footer.

First, as an element in fixed position does not occupy space on the page, you have to take into account for it by giving appropriate margins on the page, e.g.:

@page {
    margin: 5cm 0 3cm 0;
    size: A4;
}

then simply position the header and footer with respect to this margin:

header, footer {
    position: fixed;
    left: 0;
    right: 0;
}
header {
    /* subtract @page margin */
    top: 5cm;
    height: 5cm
}
footer {
    /* subtract @page margin */
    bottom: 3cm;
    height: 3cm;
}

With this you can just put arbitrary HTML in <header> and <footer> elements and they will be repeated on every page.

Page counters do not seem to work there though, so you will need to implement them based @page rules as described in the other answers.

๐Ÿ‘คDidier L

Leave a comment