Victor
Victor

Reputation: 186

Puppeteer - How to change orientation of some pages in a document?

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

Answers (3)

Max Lemieux
Max Lemieux

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 :

  • Set a different size on the pages you want to be rotated (here I change it by 0.1 inch which is about 1 pixel in the end) and assign it to your corresponding pages
    @page rotated {
       size: 8.49in 11in;
    }

    .rotated_class {
       page: rotated;
    }
  • I use 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());

  • the Page size is the only info I found that could be "transferred" from the css to the 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

Nodirbek Ergashev
Nodirbek Ergashev

Reputation: 47

We need to set 'landscape' property to 'true' in options.

var options = {
    ...
    landscape: true
}

page.pdf(options);

Upvotes: 1

Md. Abu Taher
Md. Abu Taher

Reputation: 18836

Pseudo Selectors for @page

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

Result: enter image description here

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.

Alternative way

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

Related Questions