Reputation: 186
I'm using Puppeteer to create a 30-page long pdf and a few of the pages need to be landscape orientated. How can I specify it only for page x and page y ?
Upvotes: 9
Views: 12440
Reputation: 31
Well, according to caniuse, you can use the page property with Chrome 85 and up
So you can use @page followed by a "named page name" in combination with the page property to set a different orientation (or any other properties) to any page you want.
example:
@page rotated {
size: landscape;
}
.rotated_class {
page: rotated;
}
Page example, just right click -> print to see it in action
.
.
.
.
.
Original problem, no longer relevant
Well, after writing this solution I found a major problem with the @page
approach. If you try to print the example page I linked to just above, you'll see that the viewport of the rotated pages is limited to the width of the first page if the first page is in portrait (and limited in height if the first page is in landscape).
The solution I ended up using for the page rotation is a bit whack and needs a second library, but it works :
@page rotated {
size: 8.49in 11in;
}
.rotated_class {
page: rotated;
}
pdf-lib
after the puppeteer generation to open the pdf and rotate every page smaller than a normal page (in my case I check if the width is smaller than 612 pixels) const pages = pdf.getPages();
for (let i = 0; i < pages.length; ++i) {
const pageToRotate = pages[i];
if (pageToRotate.getWidth() < 612) {
pageToRotate.setRotation(degrees(-90));
}
}
pdfBuffer = Buffer.from(await pdf.save());
pdf-lib
to flag any page to be rotated, hence why I'm using that solution.This "viewport bug" is now fixed, see the solution at the top
Upvotes: 3
Reputation: 47
We need to set 'landscape' property to 'true' in options.
var options = {
...
landscape: true
}
page.pdf(options);
Upvotes: 1
Reputation: 18836
According to the documentation or CSS spec, you can set up different orientation to some pages using CSS.
@page :pseudo-selector{
size: landscape;
}
The acceptable and working pseudo-selectors (that I tested with puppeteer and google chrome) includes,
:blank
:first
:left
:right
PS: At the moment of answer, other selectors like :nth-child
and page identifies mentioned on the draft does not work on chrome version 73.
The only other way to deal with this is to print pages separately and then merge them later on. You can print specific pages with pageRanges
,
page.pdf({pageRanges: '1-5', path: 'first.pdf'})
And use packages like pdf-merge
to merge two pdf file.
const PDFMerge = require('pdf-merge');
PDFMerge(['first.pdf', 'second.pdf'], {output: `${__dirname}/3.pdf`})
Upvotes: 9