I'm creating a document with WeasyPrint. I have sections that have names, some of which might span across multiple pages. When a section is too long, a page break occurs. What I am trying to do is to re-display the current section's name, ideally with the same formatting.
The following MWE shows how the section title is not displayed after a page break:
<html>
<body>
<h1>First section</h1>
<p>Lorem ipsum...</p>
<p>Lorem ipsum...</p>
<p>Lorem ipsum...</p>
<p>Lorem ipsum...</p>
<p style="break-after: always;"></p>
<p>Lorem ipsum...</p>
</body>
</html>
Output of weasyprint example.html example.pdf
:
I want First section
to be displayed, as a <h1>
tag, at the top on the left page.
I would like to do as this tex.stackexchange post which, as I understand it, basically consists in checking if the current page number exceeds the current total page count, and if it does, inserting the last section title encountered.
I'm not aware of the possibility to do so in HTML, does it exist?
Is there any workaround to do this? If not, is it possible to have WeasyPrint execute custom Python code on some page-break
hook?
While it is not possible at this time, you can still use an awesome workaround.
When printing, only three kind of elements are automatically reproduced on each page:
We have to use one of them to build up a css-only solution: we will choose headers. So, the first part of the question is: how can I set a different header for each page? Or, in other words, how can I set a chapter's header?
Achieving this goal is quite simple: once decided which tag or class should contain the chapter's title, set a new CSS string for it:
h1 {
string-set: doctitle content();
}
Then display the string in the header:
@page {
size: A4;
margin: 1.6cm .6cm 1.2cm .6cm;
@top-center {
content: string(doctitle);
}
}
Now you will have something like this:
Let me add some code to your:
<html>
<body>
<h1>First section</h1>
<p>Lorem ipsum...</p>
<p>Lorem ipsum...</p>
<p>Lorem ipsum...</p>
<p>Lorem ipsum...</p>
<p style="break-after: always;"></p>
<p>Lorem ipsum...</p>
<h1>Second section</h1>
<p>Lorem ipsum 2...</p>
<p>Lorem ipsum 2...</p>
<p>Lorem ipsum 2...</p>
<p>Lorem ipsum 2...</p>
<p style="break-after: always;"></p>
<p>Lorem ipsum 2...</p>
</body>
</html>
In this case your headers will be:
Next step: set same style for headers and chapter's titles, so headers can have the same appearance as titles:
h1 {
string-set: doctitle content();
font-family: 'Liberation Serif';
font-size: 28pt;
line-height: 1.2em;
}
@page {
size: A4;
margin: 1.6cm .6cm 1.2cm .6cm;
@top-left {
content: string(doctitle);
font-family: 'Liberation Serif';
font-size: 28pt;
line-height: 1.2em;
}
}
Then you will have something like this:
Now, we need to fix the latest issue: the title in the first page looks like duplicated, because of the presence of both title and header.
Fixing it is quite simple:
body h1:first-of-type {
position: absolute;
left: -30cm;
}
I have positioned the first title outside the printing area. Unfortunately setting it to display: none
will cause that not even the header will be displayed. You have other alternatives, such as visibility: hidden
or font-size: 0
or color: transparent
, but these three options will always let some blank space between the header and the first paragraph.
Now probably it's time to increase the header's height, adding top-padding to @top-left; The result should look like this:
This technique is not 100% safe: if a chapter that is not the first one will coincidentally start in a new page, both header and title will be shown, one close to the other. In any case this is not a frequent scenario.
Further improvements can consider a different approach to page breaks.
<html>
<body>
<section class="chapter">
<h1>First section</h1>
<p>Lorem ipsum...</p>
<p>Lorem ipsum...</p>
<p>Lorem ipsum...</p>
<p>Lorem ipsum...</p>
<p>Lorem ipsum...</p>
<h1>Second section</h1>
<p>Lorem ipsum 2...</p>
<p>Lorem ipsum 2...</p>
<p>Lorem ipsum 2...</p>
</section>
<section class="chapter">
<h1>Third section</h1>
<p>Lorem ipsum 3...</p>
<p>Lorem ipsum 3...</p>
<p>Lorem ipsum 3...</p>
<p>Lorem ipsum 3...</p>
</section>
</body>
</html>
Styling page-breaks on chapters, and managing title hiding for the first child of any chapter:
section.chapter {
break-after: always;
}
section.chapter h1:first-of-type {
position: absolute;
left: -30cm;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With