Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to repeat on each page of complex headers (eg, tables)? #92

Closed
pikhovkin opened this issue May 22, 2013 · 26 comments
Closed

How to repeat on each page of complex headers (eg, tables)? #92

pikhovkin opened this issue May 22, 2013 · 26 comments
Labels
CSS Questions about how to do something with CSS documentation Problems or improvements needed on the documentation or on the website feature New feature that should be supported

Comments

@pikhovkin
Copy link
Contributor

Hello!
Please tell me how to repeat on each page of complex headers (eg, tables) at the top and bottom of the page?

@barryvan
Copy link

At this stage, this isn't possible -- see this thread on the mailing list for more details. Basically, to be able to do this, the Generated Content for Paged Media spec would need to be implemented, but it's not, I believe, at a sufficiently-advanced stage for that, as it's only an Editor's Draft at present. :(

In that mailing list thread, I do suggest a (really, truly) horrible hack for getting this to work, involving stacking lots of absolutely-positioned elements on top of each other -- that might work for you, particularly if you're generating the HTML dynamically.

@SimonSapin
Copy link
Member

Hi @pikhovkin ,

As you’ve probably seen, what you can put in page-margin headers it pretty limited. You could have any element repeated in every page with position: fixed. (This used to be broken, but was fixed in version 0.19.1.) However a fixedpos element would be the same on every page, you couldn’t have eg. the current page number in there.

The hack @barryvan mentions with fixedpos elements staked on top of each other assumes that such elements are only repeated starting on the page where they are defined, but that is not the case: they are repeated on every page, including pages before.

@barryvan
Copy link

Hi @SimonSapin -- just a minor correction. If you use absolutely-positioned, rather than fixed-position, elements, they won't repeat. The only caveat is that you need to include the header content multiple times within the HTML itself to ensure that it's shown on every page.

@pikhovkin
Copy link
Contributor Author

Thanks.

Solved the problem in two passes.
First the document is rendered, and then I'm on every page (except the first) add rendering complex header (top and bottom) with a style {position: fixed}.

@SimonSapin
Copy link
Member

I’m interested, how do you do the "except the first page" part? Are the header/footer the same on every other page?

@pikhovkin
Copy link
Contributor Author

Please see here https://gist.github.com/pikhovkin/5642563

@SimonSapin
Copy link
Member

Ok, I see. You can just pass filenames instead of strings: HTML('template.html').

Also, you’re using undocumented APIs. Be aware that there is no promise that your code will still work with the next WeasyPrint version: we reserve the right to completely change undocumented implementation details.

In general this is the moment to ask if the public API should be extended to cover more use cases, but in this case I feel like this really should be a CSS feature. We’re discussing this in the CSS Working Group, there is movement to make CSS Paged Media much more powerful, but it will take a lot of time. If you want to help on that side, send use cases to www-style: http://lists.w3.org/Archives/Public/www-style/

@pikhovkin
Copy link
Contributor Author

Thanks for comments.

To solve the problem of complex headers and footers can be like in mpdf http://www.mpdf1.com/mpdf/index.php

@miracle2k
Copy link

Prince has static() and flow(), but from what I can tell, this is totally non standard, right? I'm possibly interested in implementing something along those lines - or looking into it, anyway. I don't know much about the state of paged media in CSS. The css-gcpm draft has recently been updated. Does it make sense to follow it by now?

@SimonSapin
Copy link
Member

The status of GCPM is, well, a long story. And a big mess. The original editor of GCPM left W3C’s CSS working group and republished his stuff as https://books.spec.whatwg.org/ and https://figures.spec.whatwg.org/ . Meanwhile, http://dev.w3.org/csswg/css-gcpm/ has a new editor at W3C, and the two have started diverging. There doesn’t seem to be much interest from browser vendors in either them, so it’s mostly about documenting what Prince XML and Antenna House are doing. Except there doesn’t seem to be much interest from YesLogic (Prince XML) or Antenna House in standardizing what they’re doing or getting interoperability, either.

There’s also CSS Regions http://dev.w3.org/csswg/css-regions/ , a proposal from Adobe that’s getting into IE and WebKit, which might be relevant here.

@jsenecal
Copy link

FWIW, I'm using what @pikhovkin shared and it does wonders. Like @SimonSapin mentionned - it could be nice to document those APIs.

@doekman
Copy link

doekman commented Sep 7, 2017

Hi, based on the gist of @pikhovkin, I created an extension to Flask-WeasyPrint in this gist. It's still a bit rough, but I thought to share it, report my findings and possibly get feedback.

I understand it uses undocumented API's. I take my chances, because I don't know an other way to create the PDF's I need with WeasyPrint. But documenting them would be appreciated a lot!

It uses Jinja2 to render the Overlay HTML (header/footer-HTML), so page number and number of pages can be used in HTML. Custom positioning of content can be done by supplying positions through the context which will be rendered by Jinja2.

The render method shares the stylesheets with the Overlay pages to prevent errors like "CAIRO out of memory" (I probably got this error because I used @font-face definitions, and this way, the FontConfiguration is shared).

@whitelynx
Copy link

Has there been any progress on GCPM in the last 3 years? Is it getting to a stage where we could start implementing something based on it?

@liZe
Copy link
Member

liZe commented Oct 12, 2017

Has there been any progress on GCPM in the last 3 years?

Yes, you can check what the CSSWG did.

What we want is running elements. With named pages (added in #495), we should be able to repeat complex headers in page margins.

Is it getting to a stage where we could start implementing something based on it?

Of course. Even if GCPM is "a long story" and "a big mess", running elements can IMHO be added safely to WeasyPrint. The spec didn't really change during the last years, the only reported issue even includes an interesting alternative syntax to fix it.

Implementing both syntaxes looks like a good idea for me. Even if it's a draft, the feature is useful and having it implemented may even help the CSSWG.

Anyone interested? I'll be happy to help!

@liZe
Copy link
Member

liZe commented Oct 12, 2017

@doekman

The render method shares the stylesheets with the Overlay pages to prevent errors like "CAIRO out of memory" (I probably got this error because I used @font-face definitions, and this way, the FontConfiguration is shared).

That's probably fixed now that #441 is fixed.

@biggosh
Copy link

biggosh commented Apr 25, 2018

Hi @liZe.

Is there any planned date for running and element support? I've seen the code and I've noticed there is many parts to touch. If you can give me some suggestions (what to touch and where to insert my code) I can try to start with a simple implementation.

@liZe liZe added the CSS Questions about how to do something with CSS label Sep 20, 2018
@liZe
Copy link
Member

liZe commented Sep 20, 2018

Hi @liZe.

Oh, I'm late…

Is there any planned date for running and element support?

Unfortunately, no.

I've seen the code and I've noticed there is many parts to touch. If you can give me some suggestions (what to touch and where to insert my code) I can try to start with a simple implementation.

Currently, I have no idea about how to implement that, but I can help if you're still interested (and I won't wait half a year this time).

@zilles
Copy link

zilles commented Mar 28, 2019

Just something for the next person to find this thread:
The "content" property you use in the margin boxes (@top-center) can point to an svg file with arbitrarily complex layout. I used this to create a complex header that would not have been possible with text content.

@top-center {
    content: url(header.svg);
    margin-top: auto;
    margin-bottom: 0;
    height: 1in;
}

header.svg:

<svg height="96" width="684" xmlns="http://www.w3.org/2000/svg">
	<style>
	text { fill: black; }
	.big { font: bold 16pt helvetica; }
	.small { font: 11pt helvetica; }
	</style>
	<text x="0" y="62" class="big">Big Text</text>
	<text x="0" y="83" class="small">Smaller Text</text>
</svg> 

@nathandem
Copy link
Contributor

Hi there,

I recently encountered the same header/footer problem mentioned above by several in this github issue (and elsewhere). Inspired by the examples above, I wrote a solution which is, I think, a little bit more polished and that could/should be integrated in the lib.

Here's the code:
https://gist.github.com/nathandem/63f410d501d200cfa5613b38aaf74c44

Why including this patch in the core?
Disclaimer: it doesn't try to takes into account web standards, but it will solve a major pain point for the lib users who want to create professional looking PDFs.
I had to spend a lot of time searching online plus digging on the internal API to come up with a solution, I'd like to spear this effort/time to the next users :) This is the reason why I think that the feature should be integrated in the core (and visible right away in the doc).

Next steps
If the idea of this patch gets accepted, I'd to receive some guidance from the maintainer to know 1) if there're some elements I could improve to reach the code standard of the lib, 2) where I should put the code. I guess some of it should be part of the public API (the main weasyprint/__init__.py), some may be located elsewhere (maybe weasyprint/layout/pages.py?). I will then write a PR with tests and documentation, so that everyone can solve this problem quickly from now on!

So, are you interested in me adding support for this feature in Weasyprint? :)

PS : If someone launches himself/herself in a major rewrite to support the newer standards someday (proper support of flexboxes and co), this section of the code (along others) will probably be rewritten. Yet in the meantime (it's been already 6 years!), this will help many!

Cheers!

@liZe
Copy link
Member

liZe commented Apr 17, 2019

Here's the code:
https://gist.github.com/nathandem/63f410d501d200cfa5613b38aaf74c44

Hey, that's really useful ❤️, thanks a lot for sharing this!

Why including this patch in the core?
Disclaimer: it doesn't try to takes into account web standards, but it will solve a major pain point for the lib users who want to create professional looking PDFs.

Integrating this in the core may look like a good solution, but I think it's not. WeasyPrint has a long history with web standards, and the golden rule I now know from this history is that we really often have to blindly follow specifications. There's an endless work waiting for us to implement the specs, and each time we've tried to create our own specs it ended in a bad way. Moreover, maintaining this code (ie. fixing bugs, but also adding new features, and keeping it almost forever as it would be in public API, even if it relies on WeasyPrint's internals) is not a work I want to do.

Next steps
If the idea of this patch gets accepted, I'd to receive some guidance from the maintainer to know 1) if there're some elements I could improve to reach the code standard of the lib, 2) where I should put the code. I guess some of it should be part of the public API (the main weasyprint/__init__.py), some may be located elsewhere (maybe weasyprint/layout/pages.py?). I will then write a PR with tests and documentation, so that everyone can solve this problem quickly from now on!

I really appreciate your work, the code is clean and could be really useful to a lot of people. Maybe adding it in the documentation (and probably the whole issue) is the solution for now. It also would be useful to have a place where code snippets (both CSS and Python) could be shared, but I don't know how/where to do this.

So, are you interested in me adding support for this feature in Weasyprint? :)

PS : If someone launches himself/herself in a major rewrite to support the newer standards someday (proper support of flexboxes and co), this section of the code (along others) will probably be rewritten. Yet in the meantime (it's been already 6 years!), this will help many!

Actually, supporting running elements doesn't need a major rewrite, and I think that it would be a great way to support this feature in WeasyPrint 😄. I can help, of course (but it looks like you already know WeasyPrint internals quite well!)

About a proper support of flexbox, the work mainly has to be done in flex.py and it wouldn't take a lot of work to improve the current situation (which is not that bad, is it?)

@nathandem
Copy link
Contributor

Thanks for your feedback @liZe :)

I understand your point of not wanting to include this hack in the codebase. It'd break the project rules and would have to be maintained.

I didn't actually thought about it first, but including a reference to this snippet in the documentation would in practice (almost) achieve the same result! I say almost because it wouldn't be as straightforward integrate for beginners as importing the lib and calling a method directly. But say 80% of the users should be able to go along without having to digging outside the doc, so that'd already a big improvement!

I'd suggest to add a new section in the documentation entitled "Tips & tricks" (or something along this line). This code would be the first snippet in this new section. I'd also complement it with a little explanation, an example or two and add a short reference from the tutorial part to it. The other snippets you mentioned would then go in the new section too.

Concerning the running elements, I don't want to advance myself on this - because of time, competence and motivation. But if this proposal of this new section of the doc and this code + explanation is deemed interesting, I can do that for this weekend ;)

nathandem added a commit to nathandem/WeasyPrint that referenced this issue Apr 20, 2019
By doing so, create a new section in the doc called
"Tips and tricks".

Relates Kozea#92
@tookas92
Copy link

tookas92 commented May 6, 2019

Here's the code:
https://gist.github.com/nathandem/63f410d501d200cfa5613b38aaf74c44

Hey I have problem with this solution. In my header I want to add image and everytime I render pdf instead of header image I have only alt attribute text. Why it might happen?

@nathandem
Copy link
Contributor

@tookas92 The problem may come from the fact that you use relative urls in your header and you forgot to provide a base_url. (Note: in case you are using Django, you can get the base url easily from your views with request.build_absolute_uri().)

If it doesn't help, please create gists with a copy of the relevant files + your settup and share the links here so that I can have a look ;)

@liZe
Copy link
Member

liZe commented Jul 19, 2019

Now that the documentation has been updated (thanks @nathandem!), I think that we can close this issue. Don't hesitate to add comments if you find new tricks.

@mchccc
Copy link

mchccc commented Oct 31, 2022

Just something for the next person to find this thread: The "content" property you use in the margin boxes (@top-center) can point to an svg file with arbitrarily complex layout.

@zilles those tip and snippet seem very interesting, but I wasn't able to get them to work.. do you think they're still valid after these years?

@Ravin001
Copy link

I was able to repeat the header and footer by using suggestions here, which I found is less complex for my case-
#693
e.g. for the header:

@page {
    size: letter;
    margin: 4cm 8mm 2cm;
}

.pdf-header {
    /* position fixed to repeat the header on all pages */
    position: fixed;
    top: -3.7cm;
    width: 100%;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CSS Questions about how to do something with CSS documentation Problems or improvements needed on the documentation or on the website feature New feature that should be supported
Projects
None yet
Development

No branches or pull requests