Headless PDF printing inconsistent page width and height

See original GitHub issue

I’m currently encountering some potential rounding issues with the PDF page size where I have to use an additional few 10ths of a millimetre on the width and height for the pages, the @pages declaration in my CSS, and also the CSS height of my sections to render (mostly) correctly.

Even after adding the extra mm to cover the issue, the width then increases by about 1-2mm on either side of the page, only when Puppeteer is used to generate the PDF, but not when printed as PDF directly from my local Chrome (65.0.3325.181).

The removal of the additional mm breaks the layout in both local Chrome and puppeteer rendered PDFs.

Possibly similar issue to #666.

Tell us about your environment:

What steps will reproduce the problem?

const puppeteer = require('puppeteer');
const fs = require('fs');

const DELTA = 0.27; // closest additional mm to not break layout

(async () => {
  let browser;
  try {
    browser = await puppeteer.launch({
      headless: true,
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-gpu',
        '--hide-scrollbars',
        '--disable-web-security',
      ],
    });
    const page = await browser.newPage();
    await page.goto(
      `data:text/html,${fs.readFileSync('index.html').toString('utf8')}`,
    );
    await page.pdf({
      path: './index.pdf',
      displayHeaderFooter: false,
      printBackground: true,
      pageRanges: '1-2',
      height: 139 + DELTA + 3 + 3 + 'mm', // Additional page margins of 3mm
      width: 550 + DELTA + 3 + 3 + 'mm', // Additional page margins of 3mm
      margin: {
        top: 0,
        right: 0,
        bottom: 0,
        left: 0,
      },
    });
    await browser.close();
  } catch (err) {
    if (browser) {
      await browser.close();
    }
    throw err;
  }
})();
  1. node index.js.
  2. Open PDF.
  3. Open HTML file directly in Chrome browser.
  4. Print as PDF.
  5. Compare (may have to zoom in to see).

What is the expected result?

PDF should not have any margin/whitespace on the page edges.

What happens instead?

There is a horizontal page gap on either side of each page of about 1mm. Should not need to use any additional mm adjustment - raw sizes should render as expected.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:80
  • Comments:31 (1 by maintainers)

github_iconTop GitHub Comments

16reactions
tcliftcommented, Sep 6, 2018

Approaching this from a different angle… how would one produce a 73pt × 73pt PDF (to pick an arbitrary size that doesn’t appear possible)?

There seem to be many issues raised that are related to the same rounding problem. This one is currently the highest voted. Many have suggested workarounds that don’t seem broadly applicable, or involved increasing or decreasing the page size to something that did round.

Here’s a reproduction using @page sizing:

const puppeteer = require('puppeteer');

const pt = process.argv[2];
const widthPt = pt;
const heightPt = pt;

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.emulateMedia('screen');
  await page.setContent(`<html>
  <head>
    <style>
      @page {
        size: ${widthPt}pt ${heightPt}pt;
      }
      body {
        margin: 0;
      }
    </style>
  </head>
  <body>
    <div style="width: ${widthPt}pt; height: ${heightPt}pt; background: #F00;">Page 1</div>
    <div style="width: ${widthPt}pt; height: ${heightPt}pt; background: #00F;">Page 2</div>
  </body>
</html>
`);
  await page.pdf({
    path: `${widthPt}ptx${heightPt}pt.pdf`,
    preferCSSPageSize: true,
    printBackground: true,
  });
  await browser.close();
})();

then one can inspect the output size like:

$ PT=73 && node ./index.js ${PT} && strings ./${PT}ptx${PT}pt.pdf | grep MediaBox
/MediaBox [0 0 72.959999 72.959999]
/MediaBox [0 0 72.959999 72.959999]
/MediaBox [0 0 72.959999 72.959999]

(in this example, some of the blue box extends onto page 3)

I tried various roundings to try to catch it out, but couldn’t work out what it’s doing.

pt input equiv. px (@96/in) equiv. in equiv. mm PDF pt output
73.499999 97.99999867 1.020833319 25.92916631 73.919998
73.49999 97.99998667 1.020833194 25.92916314 72.959999
73 97.33333333 1.013888889 25.75277778 72.959999
72.75 97 1.010416667 25.66458333 72.959999
72.56692913 96.75590551 1.007874016 25.6 72.959999
72.500001 96.666668 1.006944458 25.57638924 72.959999
72.5000001 96.6666668 1.006944446 25.57638892 72
72.5 96.66666667 1.006944444 25.57638889 72
72.2834645669291 96.37795276 1.003937008 25.5 72
72 96 1 25.4 72
10reactions
CaelanStewartcommented, Jul 6, 2018

@aslushnikov, just done so.

I appreciate that there’s a lot to do. Though this issue does make it impossible to output a PDF with more than one non-white page without a line at the bottom or right hand sides of the page, which for an app I’m building is an on going problem.

The use case of the PDF output is almost limitless. There is literally no other good, modern and maintained HTML5 to PDF solution out there.

I’ve just come across this issue.

Could implementing that option be of any help to this issue?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Chrome headless PDF printing does not honour @page { size ...
To fix this, a few things need to happen: 1) At the devtools level, the printToPDF command needs to have some way of...
Read more >
How can I change paper size in headless Chrome --print-to-pdf
The page size could be set in inches/mm. I haven't tested with a size in pixels. Here is a set of CSS rules...
Read more >
add customized printing setting for headless (issue ...
Sadly setting different dpi's yield the same pdf file. The reason is, the page size is computed from inch to dpi in headless...
Read more >
Understanding PDF Generation with Headless Chrome
Headless Chrome is a version of Chrome without a visible graphical ... I am also able to set the size of the window...
Read more >
Controlling the Settings in Chrome's Print Dialogue With CSS
Out of this plethora of options, five can be directly or indirectly controlled via CSS: Layout, paper size, Margins, Headers and footers, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found